我已经编写了两个函数(伪代码),用于在给定树的根的情况下计算二进制树的节点数和树高。 最重要的是,二叉树表示为第一个chiled / next兄弟格式。
所以
struct TreeNode
{
Object element;
TreeNode *firstChild;
TreeNode *nextSibling;
}
计算节点数:
public int countNode(TreeNode root)
{
int count=0;
while(root!=null)
{
root= root.firstChild;
count++;
}
return count;
}
public int countHeight(TreeNode root)
{
int height=0;
while(root!=null)
{
root= root.nextSibling;
height++;
}
return height;
}
这是我在算法书上看到的问题之一,我上面的解决方案似乎有一些问题,我也没有完全明白使用二元树的第一个孩子/右兄弟代表,你能不能伙计们给我一些想法和反馈,好吗? 干杯!
答案 0 :(得分:1)
下一个兄弟和第一个孩子的使用可能是这样的:
A1 -- A2 -- A3
| |
| B1 -- B2 -- B3
| |
D1 -- D2 C1
图中的水平线代表nextSibling
,垂直线代表firstChild
链接。对于某些问题,这可能是自然可视化(但对于其他一些问题,您可能更喜欢通常的树有两个子节点 - 它们是等效的。)
你的伪代码似乎遗漏了一些东西,因为你并没有真正计算任何东西。我想你想在count++
循环中分别height++
while
。
无论如何,要计算节点数,您需要添加子节点的数量以及同一级别(兄弟节点)上的节点数。对于相当小的树,这可以递归地完成:
public int countNode(TreeNode root) {
if (root == null) return 0;
return 1 + countNodes(root.firstChild)
+ countNodes(root.nextSibling);
}
对于较大的数据结构,您需要将“待处理”节点存储在内存堆栈中以避免堆栈溢出(原文如此!)
要计算高度,首先需要确定如何定义高度。它是您遵循firstChild
链接(即A1 -> D1
)或您想要树中最长路径(任何地方)(可能是A1 -> A2 -> B1 -> B2 -> C1
)的路径。在第一种情况下,您的实施是正确的。在第二种情况下,您需要一个类似于计数节点的递归函数(而不是添加,您将选择更大的子树)。
答案 1 :(得分:0)
虽然字面上是正确的,但“第一个孩子”和“正确的兄弟姐妹”可能会有点令人困惑。如果你用“左孩子”和“右孩子”代替,我认为你能够更好地理解它。
答案 2 :(得分:0)
要理解递归,首先必须理解递归。
public int countNode(TreeNode root)
{
if (root==null) {
return 0;
} else {
return countNode(root.firstChild) + countNode(root.nextSibling) + 1;
}
}
public int countHeight(TreeNode root)
{
if (root==null) {
return 0;
} else {
return max(countHeight(root.firstChild),
countHeight(root.nextSibling)) + 1;
}
}
如果树为空,则它不包含节点且没有高度。
如果树不为null,那么它比一个较高的子树高一个节点,它包含两个子树的所有节点,加上包含两个子树的节点。
阅读Dave Touretzky关于LISP的书。戴夫用龙故事教授递归,龙实际上是一位很好的老师。