我想到了以下几点:
看起来像这样
def treeDegenerator(self):
self.valList = []
currentNode = self
self.totalNodes = 0
self.nodes = 0
while currentNode:
while currentNode.getLeftChild():
currentNode.rotate_root_right()
self.valList.append(currentNode)
currentNode = currentNode.getRightChild()
self.totalNodes += 1
def completeTree():
for node in self.valList:
node.left = None
node.right = None
for i in range(len(self.valList)):
self.valList[i].left = self.valList[(i)*2+1]
self.valList[i].right = a.valList[(i)*2+2]
这是一个学生必须在没有任何过去考试参考的情况下编码的问题。我方法的问题是,我几乎不可能在30分钟内正确地写下所有代码,如果我事先记住一些代码,也许是可能的。我想知道是否有一个更简单、更可行和优雅的解决方案来将任何二叉树转换为适当的堆?
>
我首先将树折叠成node.right上的有序链表。
我假设我们是从一个有序的BST开始的。如果不是,那就对列表进行排序。如果您希望使用最大堆而不是最小堆,那么此时也可以反转列表。
计算节点并计算解决方案中包含的最大完整树的深度
对整个树进行递归预排序遍历,随时从列表的头部填充每个节点。
对您刚刚构建的树进行预序遍历,从列表节点填充叶子,直到用完
步骤4将按如下方式递归完成:
root = list
fillChildren(root, list.right, levels-1)
fillChildren(root, list, levels) {
if (levels < 1) {
root.left = root.right = null
return list
}
root.left = list
list = fillChildren(root.left, list.right, levels-1)
root.right = list
list = fillChildren(root.right, list.right, levels-1)
return list
}
当然,这样做的诀窍是,为了进行前序遍历而映射节点满足堆属性。
将第4步和第5步结合起来也很容易,只需跟踪一个虚拟数组堆中每个节点的索引。
只是为了好玩,整个工作是这样的:
treeToHeap(root) {
if (root == null) {
return null
}
// Convert tree to list
while(root.left != null) {
root = rotateRight(root)
}
for (n = root; n.right != null; n=n.right) {
while (n.right.left != null) {
n.right = rotateRight(n.right)
}
}
// Count nodes
count = 0
for (n = root; n!=null; n=n.right) {
count+=1
}
// Build min-heap
list = root.right
// root's index in imaginary array heap is 0
if (count>1) {
root.left = list
list = fillNodes(root.left, list.right, 1, count)
} else {
root.left = null
}
if (count>2) {
root.right = list
list = fillNodes(root.right, list.right, 2, count)
} else {
root.right = null
}
return root
}
fillNodes(root, list, heapIndex, heapSize) {
heapIndex = heapIndex*2+1
if (heapIndex < heapSize) {
root.left = list
list = fillNodes(root.left, list.right, heapIndex, heapSize)
} else {
root.left = null
}
heapIndex += 1
if (heapIndex < heapSize) {
root.right = list
list = fillNodes(root.right, list.right, heapIndex, heapSize)
} else {
root.right = null
}
return list
}
所以这花了15分钟(我没有费心写出rotateright),那是在弄清楚如何做到这一点之后。我返回了几次来修复错误。
对于一个30分钟的考试来说,这很难...但也许考试并没有真正要求堆完全平衡。如果只是实现一个就地heapify的问题,那么这是相当合理的。
从概念上讲,您可以将此任务分为两个步骤:
戴-斯托特-沃伦算法的工作原理是将树旋转成一个单链表,然后从那里进行一系列旋转,将其变成一个完美平衡的树。我不记得DSW算法是否会根据二进制堆的需要,专门将所有剩余节点放在树的最左边的底层。如果没有,您可以通过进行清理来解决这个问题:如果树没有完全2次方的节点数,请从树的底层删除所有节点,然后通过顺序遍历遍历遍历树,将它们放在最左边。
至于heapify算法:通常的做法是从底部到顶部访问树的各个层。对于每个节点,您重复地将该节点与其较小的子节点交换,直到它小于所有子节点。有了显式树结构,这可以通过优雅的递归策略来实现:
这总共需要O(n)的时间,并且只使用O(log n)的辅助存储空间,这是实现这两个算法的堆栈帧所需的空间。
这就是我到目前为止的代码(由于递归方面的困难,这并不是太多) 几乎只是将头部指针设置为中间信息(4)
下面给出了二叉树的实现。 如图中所示,树不是完整的二叉树。如何编写一个函数,将上述二叉树转换为完整的二叉树,只需将字符串数据节点添加到没有子节点的节点,即可生成完整的二叉树。 我将手动在代码中添加节点,以获得如下结果树: 但是,如何编写一个函数,它将采取根节点和返回树,这是完整的二叉树。
我如何转换使用以下代码,我的二叉树到一个简单的链表。这也许可以用递归来完成。 因此,如果根为NULL,也就是,如果函数没有收到有效的指针,则返回错误消息。 如果根是叶,这是,如果左子节点和右子节点都为NULL,您必须将其添加到叶节点列表中。
我希望将二叉树表示为数组,以便数组在数组中表示为空的广度一阶。我不想使用数组列表,但很乐意使用链表结构。我发现数组的最大大小的大小将是2^n-1,其中n是以下情况下树的高度: 数组的最小大小(除了空树或没有子项的根 [大小为 0 和 3 相应])为 (2^n - 1) - 6,在这种情况下,6 可以计算为前一个级别的空位数乘以 2: 这些树是否可以表示为堆,其中位于索引0并且当前节点在索引i处的左
我正在尝试将后缀表达式转换为二叉树。My函数将标记(字符串)列表作为参数。 每次我给函数任何输入时,调试器都会写一条消息:函数“add”中的非穷举模式。 我的想法是:一个接一个地读取标记,然后确定它是运算符还是操作数。如果是操作数,则不要将任何节点保存到树中,并将数字存储到堆栈中。否则,我用操作符创建一个节点,从堆栈中弹出符号,将它们设置为新节点的子节点,并将操作符推送到堆栈中。 如果字符串列表为
我正在研究“将排序数组转换为具有最小高度的二叉搜索树”,它问: 给定一个排序(递增顺序)数组,将其转换为最小高度的二叉树。 我无法找到为什么我的递归没有像我预期的那样停止。当7通过时,它应该停止,并且不会再次打印出7。我还发现了一个类似的答案,看起来使用了和我相同的策略,但效果很好。(我不认为我的问题与上面列出的问题重复,但我仍然想感谢您为我链接这些问题。他们给了我更多解决问题的想法。) 我的代码