ヒープの大きなトップを達成
1.ヒープとは何ですか
ヒープ構造は、完全2分木の一種です。ヒープが最大値と最小ヒープヒープに分けることができ、違いは、親ノードがすべての子ノードよりも大きいです。最大ヒープがその親ノードの子ノードよりも大きい場合、子ノードは、最小スタック親ノードよりも大きいです。図はを明確に理解を持っています:
表現の2ヒープ
実装スタックはリストを使用することができる配列に格納された各ノードのトラバーサルシーケンスの順序の値に応じてあります。親と子ノードとの間の関係があります:
1人の =親(I - 1)// 2 #取整 2は、 I + 1 * = 2を左3右= 2 * I + 2
iは、配列のインデックスを表し、左の値は、右の配列インデックスを越えて、そのノードが存在しない場合。
3.ヒープ操作
(1)スタックの値に挿入され、ふるいにかけるアップ動作:
直接使用の配列の実現が(追加時に最大ヒープに要素を追加し、我々のアプローチは)、アレイの最終用途に値を追加します。今回は、以下に示すように、最大ヒープ特性を維持する必要があります。親ノードの値と比較し、次いで90の新しいスタックの第一の端部への値、及び、値は、スイッチの位置親ノードよりも大きい場合。
ここでの問題は、親と子ノードとの間の関係に関連しています。
i及びサブスタックノードが左親ノード#との位置関係、右の 親= INT((I-1 )/ 2)# 丸め 2 =左* iが+。1 右= 2 * I + 2つの つの子ノード番号を既知の位置親ノードの位置を求めてJ、 親= INT((J-1 )/ 2)
再帰的に、ルートノードまでの比較まで。
(2)ルートノードを取得したり、削除し、ふるいにかけるダウン操作;
当我们把最大或者最小的值从堆中弹出,为了维持堆的特性,要使用sift-down操作。因为最大堆、最小堆的最值都在根节点,当弹出并返回根节点的值后,为了维持堆的特性,我们先将最后一个位置上的值放到根节点中。然后比较它与它的两个子节点中三个值的大小,选择最大的值放到父节点上。同理,我们这里也是使用递归的方式向下比较。这里涉及到两
个问题:
根据父节点确定子节点的位置:
left = 2 * ndx + 1
right = 2 * ndx + 2
交换位置要满足几个条件条件,比如跟左子节点交换的条件:
- 存在左子节点,
- 左子节点大于右子节点,
- 左子节点大于父节点
4. 堆的实现
代码:
1 class Array: 2 def __init__(self, size=32): 3 self.size = size 4 self._items = [None] * size 5 6 def __getitem__(self, index): 7 return self._items[index] 8 9 def __setitem__(self, index, value): 10 self._items[index] = value 11 12 def __len__(self): 13 return self.size 14 15 def clear(self): 16 for i in range(self.size): 17 self._items[i] = None 18 19 def __iter__(self): 20 for item in self._items: 21 yield item 22 23 24 class MaxHeap: 25 def __init__(self, maxsize=None): 26 self.maxsize = maxsize 27 self._elements = Array(maxsize) 28 self._count = 0 29 30 def __len__(self): 31 return self._count 32 33 def add(self, value): 34 if self._count > self.maxsize: 35 raise Exception('full') 36 self._elements[self._count] = value 37 self._count += 1 38 self._siftup(self._count - 1) 39 40 def _siftup(self, index): 41 if index > 0: 42 parent = (index - 1) // 2 43 if self._elements[index] > self._elements[parent]: 44 self._elements[index], self._elements[parent] = self._elements[parent], self._elements[index] 45 self._siftup(parent) 46 47 def extract(self): 48 if self._count == 0: 49 raise Exception('empty') 50 value = self._elements[0] 51 self._count -= 1 52 self._elements[0] = self._elements[self._count] 53 self._siftdown(0) 54 return value 55 56 def _siftdown(self, index): 57 left = 2 * index + 1 58 right = 2 * index + 2 59 largest = index 60 61 if (left < self._count and self._elements[left] >= self._elements[largest] 62 and self._elements[left] >= self._elements[right]): 63 largest = left 64 elif right < self._count and self._elements[right] >= self._elements[largest]: 65 largest = right 66 if largest != index: 67 self._elements[index], self._elements[largest] = self._elements[largest], self._elements[index] 68 self._siftdown(largest) 69 70 71 if __name__ == '__main__': 72 h = MaxHeap(12) 73 h.add(90) 74 h.add(60) 75 h.add(84) 76 h.add(1) 77 h.add(37) 78 h.add(4) 79 h.add(23) 80 h.add(71) 81 h.add(41) 82 h.add(29) 83 h.add(12) 84 for i in range(11): 85 print(h.extract())