在这一篇文章中,首先介绍一下堆的属性和性质。然后讲解一下建堆的过程,最后讲解堆排序。
1、堆的介绍
堆的物理存储结构就是一个一维的数组,其数据结构就是一个完全的二叉树。需要注意的是堆中的每个结点不需要后继指针,其父节点和左右孩子结点都可以通过计算得到。假设要计算结点i(i为数组的下标)的父节点和左右孩子结点,可以使用以下公式计算:
在此计算的都是结点的数组下标,
由于堆的数据结构是一个完全二叉树,设该完全二叉树有n个结点。则其内部结点下标分别为:1,2,。。。
故其叶子结点下标分别为:
堆高度:就是从根节点到最长叶子结点的距离。包含N个结点的堆高为:
其次是最大堆和最小堆问题,最大堆就是对任意的父节点的值总是大于或等于孩子节点的值,这样的话就能保证根节点保存堆中的最大元素。
即:A[parent(i)] >=A[i] (最大堆)
同样,最小堆就是对任意的父节点的值小于或等于孩子结点的值,这样就能保证根节点的值最小。
即:A[parent(i)] <=A[i] (最小堆)
一般情况下,最大堆用于堆排序中,最小堆用于优先队列中。2、建堆
根据堆的性质,我们最终要得到堆的根节点是一个最值,因而,我们需要自底向上进行建堆,若自顶向下建堆的话则不能保证根节点是最值。在此仅讨论建立最大堆的情况。
首先我们可以认为每个叶子结点已经是一个最大堆,然后从最末一个非叶子结点开始进行对调整,以满足最大堆的性质。直到到达第一个结点即根节点。在建堆中,主要有二个过程,一个是堆调整,另一个是建堆。在此,首先介绍一下对调整的过程,首先,假如要调整的结点为i,并且结点i的左右孩子已经都是最大堆。于是,我们首先计算A[i],A[ left(i) ],A[ right(i) ]的大小。1)若A[i]最大,则无需调整。2)若A[ left(i) ]最大,则将A[i]与A[ left(i) ]交换,此时最大值成为了父节点,而A[ i]到了原来的A[ left(i) ]的位置。然后又将A[ i ]与其左右孩子进行比较,直到叶子结点。同样,若A[right(i)
]最大,其操作同理可得。
void max_heapify(int A[],int i) { l=2*i; //l = left(i) r=2*i+1; //r = right(i) //heapSize为堆中实际元素的个数 if(l <= heapSize && A[l] > A[i]) //largest为i和l中的最大下标值 largest = l; else largest = i; if(l <= heapSize && A[r] > A[largest]) largest = r; if(i != largest){ swap(A[i], A[largest]); //交换 A[i]与 A[largest] max_heapify(A, largest); } }建堆的代码如下:
void build_max_heapify(int A[]) { for(int i=A.length/2; i>=1; i--) { max_heapify(A, i); } }
简单估算一下:我们在调用max_heapify的时间复杂度为:O(lgn),调用build_max_heapify的次数为:O(n)。因而,整个建堆的时间复杂度为:O(nlgn)。
不过这个时间复杂度不是渐进紧确的,因为在调用max_heapify时并不是所有的结点高度都为lgn。实际上大部分结点的高度都很小,更准确的说,高度为h的结点个数至多有个,而在高度为h的结点上运行max_heapify的代价为:O(h)。因此,我们可以计算build_max_heapify的总代价为:
最后得到构造一个最大堆的时间复杂度为:O(n)。即在线性时间内,可以把一个无序数组构造成为一个最大堆。
3、堆排序
排序思想:首先使用build_max_heapify将数组A[1,2,…,n]建成最大堆,然后将A[1]与A[n]的互换,然后再使用max_heapify调整数组A[1,2,…,n-1]成最大堆,然后将A[1]与A[n-1]互换,依次类推,最终得到一个升序的数组A[1,2,…,n]。void heapSort() { build_max_heapify(A); int heapSize = A.length; //heapSize=A.length-size while(heapSize > 1) { swap(A[1], A[heapSize]); //交换 A[1]与 A[heapSize] heapSize --; max_heapify(A,1); } }时间代价分析:build_max_heapify的时间代价是:O(n), 调用了n-1次的max_heapify,每次的时间为:O(lgn)。故heapSort的总时间复杂度为:O(nlgn)。
不知道公式怎么加到文章中,这个暂时做成图片传上来了,导致文章的排版比较乱!
来源:https://www.cnblogs.com/liuwu265/p/4032144.html