1.伙伴地址
二进制地址为011011110000,大小为(4)10和(16)10块的伙伴地址分别为:_________,_________。
地址011011110000,可以被2^(2+1)整除,所以伙伴地址是其下半部,加4就行,所以答案是011011110100; 16大小时,不能被2^(4+1)整除,所以伙伴地址是其上半部,地址减去16,结果为0110 1110 0000。至于为什么这样整除决定,请查看伙伴地址定义
2.如何判断一棵二叉树是否是平衡二叉树
平衡二叉树的定义,如果任意节点的左右子树的深度相差不超过1,那这棵树就是平衡二叉树。
算法思路:先编写一个计算二叉树深度的函数GetDepth,利用递归实现;然后再递归判断每个节点的左右子树的深度是否相差1
static int GetDepth(BinNode root) { if (root == null) return 0; int leftLength = GetDepth(root.Left); int rightLength = GetDepth(root.Right); return (leftLength > rightLength ? leftLength : rightLength) + 1; }注意这里的+1,对应于root不为空(算作当前1个深度)
static bool IsBalanceTree(BinNode root) { if (root == null) return true; int leftLength = GetDepth(root.Left); int rightLength = GetDepth(root.Right); int distance = leftLength > rightLength ? leftLength - rightLength : rightLength - leftLength; if (distance > 1) return false; else return IsBalanceTree(root.Left) && IsBalanceTree(root.Right); }上述程序的逻辑是,只要当前节点root的Left和Right深度差不超过1,就递归判断Left和Right是否也符合条件,直到为Left或Right为null,这意味着它们的深度为0,能走到这一步,前面必然都符合条件,所以整个二叉树都符合条件。
3.如何不用递归实现二叉树的前序/后序/中序遍历?
算法思想:三种算法的思想都是让root的Left的Left的Left全都入栈。所以第一个while循环的逻辑,都是相同的。
下面详细分析第2个while循环,这是一个出栈动作,只要栈不为空,就始终要弹出栈顶元素,由于我们之前入栈的都是Left节点,所以每次在出栈的时候,我们都要考虑Right节点是否存在。因为前序/后序/中序遍历顺序的不同,所以在具体的实现上有略为区别。
1)前序遍历
这个是最简单的。
前序遍历是root->root.Left->root.Right的顺序。
因为在第一个while循环中,每次进栈的都可以认为是一个root,所以我们直接打印,然后root.Right和root.Left先后进栈,那么出栈的时候,就能确保先左后右的顺序。
static void PreOrder(BinNode root) { Stack stack = new Stack(); BinNode temp = root; //入栈 while (temp != null) { Console.WriteLine(temp.Element); if (temp.Right != null) stack.Push(temp.Right); temp = temp.Left; } //出栈,当然也有入栈 while (stack.Count > 0) { temp = (BinNode)stack.Pop(); Console.WriteLine(temp.Element); while (temp != null) { if (temp.Right != null) stack.Push(temp.Right); temp = temp.Left; } } }
//后序遍历比较麻烦,需要记录上一个访问的节点,然后在本次循环中判断当前节点的Right或Left是否为上个节点,当前节点的Right为null表示没有右节点。 static void PostOrder(BinNode root) { Stack stack = new Stack(); BinNode temp = root; //入栈 while (temp != null) { if (temp != null) stack.Push(temp); temp = temp.Left; } //出栈,当然也有入栈 while (stack.Count > 0) { BinNode lastvisit = temp; temp = (BinNode)stack.Pop(); if (temp.Right == null || temp.Right == lastvisit) { Console.WriteLine(temp.Element); } else if (temp.Left == lastvisit) { stack.Push(temp); temp = temp.Right; stack.Push(temp); while (temp != null) { if (temp.Left != null) stack.Push(temp.Left); temp = temp.Left; } } } }
//中序遍历,类似于前序遍历 static void InOrder(BinNode root) { Stack stack = new Stack(); BinNode temp = root; //入栈 while (temp != null) { if (temp != null) stack.Push(temp); temp = temp.Left; } //出栈,当然也有入栈 while (stack.Count > 0) { temp = (BinNode)stack.Pop(); Console.WriteLine(temp.Element); if (temp.Right != null) { temp = temp.Right; stack.Push(temp); while (temp != null) { if (temp.Left != null) stack.Push(temp.Left); temp = temp.Left; } } } }