堆与堆排序
2016-01-09 17:35
190 查看
转载自:http://www.cnblogs.com/AndyJee/p/4612821.html
(算法)堆与堆排序
主要内容:1、什么是堆?
2、如何建堆
3、堆排序
4、参考代码
一、什么是堆?
“堆”是个很有趣的数据结构,是个完全二叉树。“堆”的特性:每个节点的键值一定总是大于(或小于)它的父节点(大于:称为“最大堆”,小于:称为“最小堆”),或者说每个节点总是大于或小于它的子节点。
对于最大堆而言,根节点为最大值;对于最小堆而言,根节点为最小值。
通常“堆”是通过数组来实现的,这样可以利用数组的特点快速定位指定索引的元素。
因此,当我们得知某个节点的索引为 i 时,可以通过以下“堆”的定义很容易地定位到它的子节点和父节点。
在起始索引为 0 的“堆”中:
1) 堆的根节点将存放在位置 0
2) 节点 i 的左子节点在位置 2 * i + 1
3) 节点 i 的右子节点在位置 2 * i + 2
4) 节点 i 的父节点在位置 floor( (i - 1) / 2 ) : 注 floor 表示“取整”操作
在起始索引为 1 的“堆”中:
1) 堆的根节点将存放在位置 1
2) 节点 i 的左子节点在位置 2 * i
3) 节点 i 的右子节点在位置 2 * i + 1
4) 节点 i 的父节点在位置 floor( i / 2 ) : 注 floor 表示“取整”操作
二、如何建堆?
根据上述对于堆的定义,建立一个堆,首先需要构建一棵完全二叉树,树的节点需要满足:每个节点的值都不大于或不小于其父节点的值,即A[PARENT[i]] >=/<= A[i]。给定一个无序数组,如何构建一个最大堆呢?
首先,将该无序数组构建为一棵完全二叉树,然后根据每个节点需要满足的条件,进行二叉树的调整。
建立一个最大堆,而建堆的核心内容是调整堆,使二叉树满足堆的定义(每个节点的值都不大于其父节点的值)。
调堆的过程应该从最后一个非叶子节点(最后一个节点的父节点)开始,假设有数组A = {1, 3, 4, 5, 7, 2, 6, 8, 0}。
那么调堆的过程如下图,数组下标从0开始,A[3] = 5开始,分别与左孩子和右孩子比较大小,如果A[3]最大,则不用调整,否则和孩子中的值最大的一个交换位置,在图1中是A[7] > A[3] > A[8],所以A[3]与A[7]对换,从图1.1转到图1.2。
所以建堆的过程就是
?
如果初始数组是非降序排序,那么就不需要调堆,直接就满足堆的定义,此为最好情况,运行时间为Θ(1);
如果初始数组是如图1.5,只有A[0] = 1不满足堆的定义,经过与子节点的比较调整到图1.6,但是图1.6仍然不满足堆的定义,所以要递归调整,一直到满足堆的定义或者到堆底为止。
如果递归调堆到堆底才结束,那么是最坏情况,运行时间为O(h) (h为需要调整的节点的高度,堆底高度为0,堆顶高度为floor(logn) )。
调堆的时间复杂度:O(logn)
建堆的时间复杂度:O(n)
关于时间复杂度的分析:参考http://www.cnblogs.com/zabery/archive/2011/07/26/2117103.html
三、如何进行堆排序?
根据“堆”的特性,我们可以从无序序列的最后一个节点的父节点开始,对其进行“下移”操作,直到序列的第一个节点为止。这样就可以保证每个节点都在合适的位置上,也就建立起了一个“堆”。但是“堆”并不是一个完全排序的序列,因为“堆”只保证了父节点与子节点的位置关系,但并不保证左右子节点的位置关系。那么我们如何进行“堆排序”呢?
由于一个“堆”的根节点必然是整个序列中最大的元素,因此对于一个排序的序列而言,每个“堆”中我们只能得到一个有效的元素。如果我们拿掉根节点,再对剩下的序列重新排列组成一个“堆”,反复如此,我们就可以依次得到一个完整的排序序列了。
当然,为了简化操作,每次我们只需要把根节点与最后一个位置的节点交换,然后把最后一个位置排除之外,对根节点进行“下移”操作即可。
堆排序的时间复杂度:O(nlogn)
关于时间复杂度的分析:参考http://www.cnblogs.com/zabery/archive/2011/07/26/2117103.html
建堆完成之后,堆如图1.7是个大根堆。
将A[0] = 8 与 A[heapLen-1]交换,然后heapLen减一,如图2.1,然后AdjustHeap(A, heapLen-1, 0),如图2.2。如此交换堆的第一个元素和堆的最后一个元素,然后堆的大小heapLen减一,对堆的大小为heapLen的堆进行调堆,如此循环,直到heapLen == 1时停止,最后得出结果如图3。
四、代码
?五、参考文章
http://www.cnblogs.com/zabery/archive/2011/07/26/2117103.htmlhttp://wxg6203.iteye.com/blog/668968