目錄node
相同:python
不一樣:算法
僅包含一個結點的有序樹是一棵二項樹(B_0樹)。二項樹B_k由兩棵B_{k-1}樹組成,其中一
棵B_{k-1}樹的根做爲另外一棵B_{k-1}樹根的最左孩子(k≥0)。
數組
proof:主要依靠B_k與B_{k-1}間的關係數據結構
它是由一系列二項樹組成的集合,知足如下性質:
堆中每一顆二項樹都知足最小堆性質。堆中度爲k的樹是惟一的 => n個結點的二項堆中最多有
lgn上界 + 1課二項樹app
根表 root list
head[H]->B_0->B_2->B_3
根表是單鏈表,它連接全部二項樹的根結點,且按度的遞增順序連接。ide
class Node(): """ class of the node in the heap provide functions to the binomial tree """ def __init__(self, key = None): self.p = None # point to parent self.key = key # value self.degree = 0 # count of the children self.child = None # point to child of the left self.sibling = None # point to the right brother def link_tree(self, other): """ other -> subtree of self. """ other.parent = self other.sibling = self.child self.child = other self.degree += 1
合併兩個二項堆
step1:按照二項樹的度遞增的順序合併兩個根表。
step2:根表調整,以知足度的惟一性。用三個輔助指針(per、p、after)將度重複的樹合併。
因爲step1合併後的根表中,度相同的樹最多有兩顆,因此會出現如下幾種狀況:
case1:三個指針所指二項樹根都存在,且度不一樣 => 指針後滑,進入case3或結束。
case2:per爲空,p.degree = after.degree,且after.sibling存在 =>指針後滑,進入case4。
case3:case1或case2不成立,若pre爲空,則必定有p.degree = after.degree => 根據degree
合併p和after所指二項樹,after後滑,進入case2 或 case1
case4:三個指針所指二項樹根都存在,且度相同 =>根據degree合併p和after所指二項樹,after
後滑,進入case3。this
def _merge_rootlist(self, heap2): """ merge two root list and keep increasing order in degree. """ p1 = self.head p2 = heap2.head if not p1: # p1 = None return heap2.head if not p2: # p2 = None return self.head if p1.degree <= p2.degree: p = p1 p1 = p1.sibling else: p = p2 p2 = p2.sibling head = p while p1 and p2: if p1.degree <= p2.degree: p.sibling = p1 p1 = p1.sibling else: p.sibling = p2 p2 = p2.sibling p = p.sibling if p2: p.sibling = p2 else: p.sibling = p1 return head
def _union(self, heap2): """ step1: merge two root list and keep increasing order in degree. step2: adjust root(merge) to keep the unique of the degree in all binomial trees. use three point to adjust the heap: pre , p , after """ if heap2 is None: return if self.head is None: self.head = heap2.head self.size = heap2.size return # step1 head = self._merge_rootlist(heap2) print("merge root list") self.print_rootlist() # step2 use three point to adjust the heap if not head: print("merge rootlist error") return pre = None p = head after = head.sibling while after: # case 1 / case 2 , point + 1 if p.degree != after.degree or (after.sibling is not None and after.sibling.degree == p.degree ): pre = p p = after # case 3, merge p and after into p elif p.key <= after.key: # update point p.sibling = after.sibling # merge two tree, p.child = after p.link_tree(after) else: # after.degree == p.degree, after.sibling = None, p.key>after.key # => update head ,link(after,p),over! if pre == None: head = after # upfate pre.sibling = after, link(after,p) else: pre.sibling = after after.link_tree(p) p = after after = p.sibling self.head = head self.size += heap2.size return
def insert(self, node): """ insert a node into a null heap. 1. node->new heap (heap2) 2. union(self, heap2) """ h = BinomialHeap() h.head = node self.union(h) self.size += 1
def extract_min_node(self): self._extract_min_node() return def _extract_min_node(self): size = self.size min_node, pre_min = self.min() self.extract(min_node, pre_min) self.size = size - 1 return def extract(self, node, pre_node): if node == None: return # del min node in the root list if pre_node==None: self.head = min_node.sibling else: pre_node.sibling = node.sibling # if the minimum node has no child if(node.child == None): return # if the node has subtrees, then inesrt them into a new heap, and union this new heap with old heap. new_heap = BinomialHeap() # insert the subtrees in reverse order p = node.child list_root = [] while p.sibling != None: p.parent = None list_root.append(p) p = p.sibling list_root.append(p) while list_root != []: p = list_root.pop(-1) new_heap.insert(p) # union self.union(new_heap) return
def _decrease_key(self,node,key): if node == None or node.key <= key: print("node or key err") return node.key = key x = node p = node.p # bubble while p is not None and p.key > x.key: t = p.key p.key = x.key x.key = t x = p p = p.p return
《算法導論》指針