给定完整二叉树的前序遍历,其中每个节点都标记为叶节点或内部节点,是否有一个好的算法来找到树的高度?例如,如果 N 代表一个内部节点,L 代表一个叶子,那么给定前序遍历 NLNNLLL,高度将为 3。
1 回答
好吧,我不禁为我们将 marti 留在评论中而感到难过。我认为他真的不知道从哪里开始,并且至少表明他已经考虑过这个问题。
我们对完全二叉树了解多少?每个节点要么是叶子,要么有两个孩子。
前序遍历递归地访问根,左子树,然后右子树。
想一想这个问题:在(完整二叉树的)前序遍历中的什么时候,我们知道我们已经用尽了一个子树?我们将访问它的根,然后访问两片叶子(如果是叶子,则只访问根)。
让我们制作一个特殊结构的堆栈:
struct StackNode{
size_t count; //initialize to 0
char nodeType; //'N' or 'L'
};
这个“StackNode”对象将使用“nodeType”变量跟踪我们在前序遍历中访问的节点类型,这应该很清楚。我们还有一个特殊的计数器“计数”,我们将其初始化为 0。
解决方案背后的想法是这样的:
- 每次遇到“N”时,创建一个 StackNode,并将其压入堆栈。
- 每次遇到“L”时,创建一个 StackNode,并将其压入堆栈
- 如果您压入堆栈的最后一个节点是“L”,则弹出最后一个节点,然后将 stack.top() 的计数加 1
- 如果 stack.top() 的计数为 2,则从堆栈中弹出顶部,然后将 stack.top() 的计数增加 1(重复直到堆栈为空或您已停止从堆栈中弹出)
每次将节点压入堆栈时,都可以检查树的当前高度。它是您的 stack-1 中的项目数(说明底部的项目是根)。
只要您跟踪到目前为止遇到的最大高度,您就会找到树的高度。
让我们来看看你的例子:NLNNLLL
堆栈最初是空的。
int maxHeight = -1;
处理第一个字符:N
将一个节点压入堆栈:
堆栈:类型计数
N, 0
最大高度 = 0;
处理下一个字符:L
将一个节点压入堆栈:
- L, 0
N, 0
最大高度 = 1;//(增加1)
最后处理的字符是叶子,所以弹出并递增:
堆:
N, 1
最大高度 = 1;
处理下一个字符:N
将一个节点压入堆栈:
- N, 0
N, 1
最大高度 = 1;//不变
处理下一个字符:N
将一个节点压入堆栈:
- N, 0
- N, 0
N, 1
最大高度 = 2;//(增加1)
处理下一个字符:L
将一个节点压入堆栈:
- L, 0
- N, 0
- N, 0
N, 1
最大高度 = 3;//递增1
最后一个节点是叶子,所以pop和increment
堆:
- N, 1
- N, 0
N, 1
最大高度 = 3;//不变
处理下一个字符:L
将一个节点压入堆栈:
- L, 0
- N, 1
- N, 0
N, 1
最大高度 = 3;//不变
最后一个节点是叶子,所以弹出并递增:
- N, 2
- N, 0
- N, 1
顶部节点的计数为 2,因此弹出并递增:
- N, 1
- N, 1
处理下一个节点:L
将一个节点压入堆栈:
- L, 0
- N, 1
N, 1
最大高度 = 3;//不变
最后一个节点是叶子,所以弹出并递增:
- N, 2
- N, 1
顶部节点的计数为 2,因此弹出并递增:
- N, 2
顶部节点的计数为 2,因此弹出并递增:
(empty stack), finished
maxHeight = 3; //the maximum height discovered during a preorder of a full binary tree