二叉堆
一个
结构
二进位堆是
- 二叉树是
完整的 ,即除最底层外的每一层都被完全填充,最底层的节点尽可能向左定位。Max-heap属性:每个节点的键都大于或等于其子节点。
注意,二叉树不强制兄弟节点之间进行任何排序。还要注意
每个节点都小于或等于其子节点的二进制堆称为A
一个简单的实现方法是将列表存储在树中,每个节点的左子节点都编号
为了理解这一点,考虑下面节点中的编号:
为了简单起见,我们保留
增加键和插入
首先,假设我们已经有了一个二进位堆。当已知索引的键值增加时,我们应该如何处理?
- 如果新键仍然小于它的父键,则没问题。
否则,将该键与其父键交换(float up)。保持向上浮动,直到键达到一个足够好的位置。
插入
对于插入,我们将一个值附加到二叉树的末尾,然后根据需要向上浮动它。这和
让我们看看如何将46插入到这个堆中。
建立一个堆
构建堆现在很简单。我们所做的只是从空堆开始重复插入键。
然而,还有一种更好的方法,我们接下来就会看到。
复杂性
这两种操作在最坏的情况下都要遍历树的整个高度,需要花费时间
建立一个堆
构建最大堆的一个更好的方法是:
- 任意位置的键。
对于从最低级别到最高级别的所有节点,运行 maxHeapify .
这是可行的,因为只有一个键的子树已经是堆了我们一路都在建立堆。
复杂性
你可以通过添加证明来帮助我。
给定一个数组
元素,上面的算法将它们排列成一个Max堆 (n)时间。
最大堆化和提取
假设有一个二叉树,它的根没有被正确地放置,但其他所有东西都是完整的,即左右子树都是完美二叉堆,但根不满足堆的属性。你将如何安排根节点在它的完美位置?当然是把它沉下去!
将有问题的节点与它的两个子节点中较大的节点交换(想想为什么!),并继续交换,直到它达到一个位置,它要么比它的子节点大,要么是一个叶节点(无子节点)。
这个过程叫做
提取
复杂性 比如插入,最坏的情况是遍历整个高度。因此,这些操作是相互配合的extractMax返回并删除堆中键最大的节点。我们是这样做的:
堆排序
主要文章:
堆排序
注意我们每次运行
- 构建要排序的元素的最大堆。
创建一个空数组,并依次用 extractMax 依次在堆上运行。扭转数组。
这需要 堆排序不仅专属于二进制堆;可以有效地利用各种堆。
示例实现
Python
12 34 56 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 69 70 72 73 74 75 76
# max-heap实现类BinaryHeap:#为了简单起见,让我们保留第0个节点不使用树=[0]#,让我们来定义自我。左而且正确的孩子s and the parent左=λ自我,n:2*n正确的=λ自我,n:2*n+1父=λ自我,n:n/2defincreaseKey(自我,指数,关键):断言自我.树[指数]<关键#改变值自我.树[指数]=关键#和浮动而指数>1而且自我.树[自我.父(指数)]<自我.树[指数]:自我.树[自我.父(指数)),自我.树[指数]=自我.树[指数),自我.树[自我.父(指数)]指数=自我.父(指数)def插入(自我,关键):#在树的末尾加上-∞自我.树.附加(-浮动(“正”))#和float将其增加到key自我.increaseKey(len(自我.树)-1,关键)defmaxHeapify(自我,指数):而(自我.左(指数)<len(自我.树)而且自我.树[指数]<自我.树[自我.左(指数)))或\( 自我.正确的(指数)<len(自我.树)而且自我.树[指数]<自我.树[自我.正确的(
12 34 56 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 69 70 72 73 74 75 76 |
|