所以我正在做一些功课,我必须完成一个大小平衡的二叉树堆实现,而我的入队函数遇到了一些麻烦。我们得到了一些代码开始,我对如何访问类等有点困惑。在下面的代码中,我写的唯一的东西是空函数(如果它没有传递给树,它不起作用,但我现在不太担心它。)和enqueue函数确实添加了前三个元素(我不确定它是否正确添加)然后失败。我认为我在enqueue函数中遇到的问题是我不确切知道如何将TreeNode添加到堆中,以及如何正确访问“heap.lchild.size”之类的内容,如果这样甚至可能的话。当我们完成时,被注释掉的结尾应该被用来测试我们的程序,但是我把它评论出来并复制了一段只测试入队函数的文件。
import random
class TreeNode( object ):
"""
A (non-empty) binary tree node for a size-balanced binary tree heap.
SLOTS:
key: Orderable
value: Any
size: NatNum; the size of the sub-tree rooted at this node
parent: NoneType|TreeNode; the parent node
lchild: NoneType|TreeNode; the node of the left sub-tree
rchild: NoneType|TreeNode; the node of the right sub-tree
"""
__slots__ = ( 'key', 'value', 'size', 'parent', 'lchild', 'rchild' )
def __init__( self, key, value, parent ):
self.key = key
self.value = value
self.size = 1
self.parent = parent
self.lchild = None
self.rchild = None
def __str__( self ):
slchild = str(self.lchild)
srchild = str(self.rchild)
skv = str((self.key, self.value)) + " <" + str(self.size) + ">"
pad = " " * (len(skv) + 1)
s = ""
for l in str(self.lchild).split('\n'):
s += pad + l + "\n"
s += skv + "\n"
for l in str(self.rchild).split('\n'):
s += pad + l + "\n"
return s[:-1]
class SBBTreeHeap( object ):
"""
A size-balanced binary tree heap.
SLOTS:
root: NoneType|TreeNode
"""
__slots__ = ( 'root' )
def __init__( self ):
self.root = None
def __str__( self ):
return str(self.root)
def checkNode( node, parent ):
"""
checkNode: NoneType|TreeNode NoneType|TreeNode -> Tuple(NatNum, Boolean, Boolean, Boolean, Boolean)
Checks that the node correctly records size information,
correctly records parent information, satisfies the
size-balanced property, and satisfies the heap property.
"""
if node == None:
return 0, True, True, True, True
else:
lsize, lsizeOk, lparentOk, lbalanceProp, lheapProp = checkNode( node.lchild, node )
rsize, rsizeOk, rparentOk, rbalanceProp, rheapProp = checkNode( node.rchild, node )
nsize = lsize + 1 + rsize
nsizeOk = node.size == nsize
sizeOk = lsizeOk and rsizeOk and nsizeOk
nparentOk = node.parent == parent
parentOk = lparentOk and rparentOk and nparentOk
nbalanceProp = abs(lsize - rsize) <= 1
balanceProp = lbalanceProp and rbalanceProp and nbalanceProp
nheapProp = True
if (node.lchild != None) and (node.lchild.key < node.key):
nheapProp = False
if (node.rchild != None) and (node.rchild.key < node.key):
nheapProp = False
heapProp = lheapProp and rheapProp and nheapProp
return nsize, sizeOk, parentOk, balanceProp, heapProp
def checkHeap( heap ):
"""
checkHeap: SBBTreeHeap -> NoneType
Checks that the heap is a size-balanced binary tree heap.
"""
__, sizeOk, parentOk, balanceProp, heapProp = checkNode( heap.root, None )
if not sizeOk:
print("** ERROR ** Heap nodes do not correctly record size information.")
if not parentOk:
print("** ERROR ** Heap nodes do not correctly record parent information.")
if not balanceProp:
print("** Error ** Heap does not satisfy size-balanced property.")
if not heapProp:
print("** Error ** Heap does not satisfy heap property.")
assert(sizeOk and parentOk and balanceProp and heapProp)
return
def empty(heap):
"""
empty: SBBTreeHeap -> Boolean
Returns True if the heap is empty and False if the heap is non-empty.
Raises TypeError if heap is not an instance of SBBTreeHeap.
Must be an O(1) operation.
"""
if not SBBTreeHeap:
print("** Error ** Heap is not an instance of SBBTreeHeap.")
if heap.root == None:
return True
else:
return False
def enqueue( heap, key, value ):
"""
enqueue: SBBTreeHeap Orderable Any -> NoneType
Adds the key/value pair to the heap.
Raises TypeError if heap is not an instance of SBBTreeHeap.
Must be an O(log n) operation.
"""
# print('heap has entered enqueue')
# print(str(heap))
if empty(heap):
heap.root = TreeNode(key, value, None)
if heap.root.size < 3:
if heap.root.lchild != None:
if heap.root.rchild == None:
heap.root.rchild = TreeNode(key, value, heap.root)
heap.root.size += 1
elif heap.root.lchild == None:
heap.root.lchild = TreeNode(key, value, heap.root)
heap.root.size += 1
else:
if heap.lchild.size >= heap.rchild.size:
heap.lchild = TreeNode(key, value, heap.root)
else:
heap.rchild = TreeNode(key, value, heap.root)
def frontMin( heap ):
"""
frontMin: SBBTreeHeap -> Tuple(Orderable, Any)
Returns (and does not remove) the minimum key/value in the heap.
Raises TypeError if heap is not an instance of SBBTreeHeap.
Raises IndexError if heap is empty.
Precondition: not empty(heap)
Must be an O(1) operation.
"""
## COMPLETE frontMin FUNCTION ##
def dequeueMin( heap ):
"""
dequeueMin: SBBTreeHeap -> NoneType
Removes (and does not return) the minimum key/value in the heap.
Raises TypeError if heap is not an instance of SBBTreeHeap.
Raises IndexError if heap is empty.
Precondition: not empty(heap)
Must be an O(log n) operation.
"""
## COMPLETE dequeueMin FUNCTION ##
def heapsort( l ):
"""
heapsort: ListOfOrderable -> ListOfOrderable
Returns a list that has the same elements as l, but in ascending order.
The implementation must a size-balanced binary tree heap to sort the elements.
Must be an O(n log n) operation.
"""
## COMPLETE heapsort FUNCTION ##
######################################################################
######################################################################
if __name__ == "__main__":
# R = random.Random()
# R.seed(0)
# print(">>> h = SBBTreeHeap()");
# h = SBBTreeHeap()
# print(h)
# checkHeap(h)
# for v in "ABCDEFGHIJKLMNOPQRSTUVWXYZ":
# k = R.randint(0,99)
# print(">>> enqueue(h," + str(k) + "," + str(v) + ")")
# enqueue(h, k, v)
# print(h)
# checkHeap(h)
# while not empty(h):
# print(">>> k, v = frontMin(h)")
# k, v = frontMin(h)
# print((k, v))
# print(">>> dequeueMin(h)")
# dequeueMin(h)
# print(h)
# checkHeap(h)
# for i in range(4):
# l = []
# for x in range(2 ** (i + 2)):
# l.append(R.randint(0,99))
# print(" l = " + str(l))
# sl = heapsort(l)
# print("sl = " + str(sl))
#
#heap = SBBTreeHeap()
#print(empty(heap))
R = random.Random()
R.seed(0)
print(">>> h = SBBTreeHeap()");
h = SBBTreeHeap()
print(h)
checkHeap(h)
for v in 'ABCDEFG':
k = R.randint(0,99)
print(">>> enqueue(h," + str(k) + "," + str(v) + ")")
enqueue(h, k, v)
print(h)
checkHeap(h)
答案 0 :(得分:0)
不要担心if size < 3
的东西。
我建议你先写出frontMin
,这应该很容易。
然后你可以写heapsort
。它应该主要调用其他方法,而不是自己做任何努力。
添加/ enqueue
时,您需要担心以下四种情况:
其中一些案例比其他案件简单得多。
dequeueMin
会有同样的考虑因素。
我建议你仔细阅读the wiki page。
我建议先建立一个二进制堆,然后确保它的大小平衡。
其中一些案件很容易,有些则不然。
答案 1 :(得分:0)
你所拥有的是一个良好的开端,因为它确实适用于前3个元素。要使其适用于所有情况,您需要知道每个新TreeNode应该去哪里。在普通二进制堆的情况下,我们知道新节点将进入底层最左边的空闲点。但是对于大小平衡的二叉树,它需要满足“每个节点的两个子树的大小从不相差超过1”的约束(实验室讲义的第1页)。要确保这一点成立,您需要替换向root的左子项和右子项添加新节点。
如果TreeNode的左侧孩子的大小为k
,而右侧孩子的大小为k-1
,则您希望添加到正确的子树(如果不是,则为大小;左右子树的数量将因2)而异。
如果TreeNode的左右子项都具有相同的大小,那么只要您保持一致,添加新节点的子树就没关系。
当您查看的当前节点的大小大于2时(意味着它同时具有左子节点和右子节点),这两点将涵盖。另外两种情况是节点的大小为2(有1个子节点)或1(有0个子节点)。如果大小为2,只需将新节点添加到任何一方为空,如果大小为1,则可以选择添加新节点的哪一侧,但要保持一致。找到添加新节点的位置后,在其键小于其父键的情况下进行筛选。
出队有点复杂。您需要找到刚刚添加的堆中的位置,将其与根交换,删除该位置(现在具有root的键/值),并在其根密钥大于其子密钥时筛选根节点(两个孩子的最小孩子的钥匙)。
对于enqueue和dequeue,请记住在堆中或堆上时更新受影响节点的大小。
希望有所帮助。