二叉堆
一个
结构
二进制堆是a
- 二叉树是
完整的 ,即除最底层外的每一层都被完全填充,最底层的节点尽可能位于左侧。Max-heap属性:每个节点的键都大于或等于它的子节点。
注意,二叉树没有强制兄弟节点之间的任何排序。还要注意
每个节点都小于或等于它们的子节点的二进制堆称为A
一个简单的实现方法是将列表存储在树中,每个节点的左子节点都编号
要理解这一点,请考虑以下节点中的编号:
为了简单起见,我们保留
增加键和插入
首先,让我们假设我们已经有一个二进制堆。当已知索引的键值增加时,我们应该如何处理?
- 如果新键仍然小于它的父键,那么就没有问题。
否则,与其父节点的密钥交换(向上浮动)。继续向上浮动,直到键到达一个足够好的位置。
插入
对于插入,我们将一个值附加到二叉树的末尾,然后根据需要向上浮动它。这和
让我们看看如何向这个堆中插入46。
建立一个堆
现在构建堆非常简单。我们所做的就是从空堆开始重复插入键。
然而,有一个更好的方法,我们将在下面看到。
复杂性
这两种操作在最坏的情况下都要遍历树的整个高度,需要花费时间
建立一个堆
创建最大堆的一个更好的方法是:
- 任意放置键。
对于从最低层到顶部的所有节点,运行 maxHeapify .
这是可行的,因为只有一个键的子树已经是堆了,而且我们一直在构建堆。
复杂性
您可以通过添加证明来提供帮助。
给定一个数组
元素,上述算法将它们排列到一个Max堆中 (n)时间。
Max Heapify和Extraction
假设有一棵二叉树,它的根位置不正确,但其他部分都是完整的,即左右子树都是完美的二叉堆,但根不满足堆属性。如何将根节点安排在最佳位置?当然是把它沉下去!
将有问题的节点与它的两个子节点中较大的节点交换(想想为什么!),并继续交换,直到它达到一个位置,该位置要么比它的子节点大,要么是叶节点(无子节点)。
这个过程叫做
提取
复杂性 和插入一样,最糟糕的情况是遍历整个高度。因此,这些操作是合用的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 40 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 68 69 70 71 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 40 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 68 69 70 71 72 73 74 75 76 |
|