堆排序

  (二叉)堆数据结构是一种数组对象,可以看做成一个完全二叉树,除最后一层外树的每一次都必须填满。下面给出数组与树之间的关系图:

 

  为了满足堆的有关性质,数组下标应从1开始记起。可以看出在这个所谓堆的二叉树中其子节点与父节点满足的关系为 parent(i) = i/2,即下标为 i 的节点的父节点为下标为 i/2 的节点;left(i) = i*2,即下标为 i 的节点的左子节点为下标为 i*2 的节点; right(i) = i*2+1,即下标为i的节点的右子节点为下标为 i*2+1 的节点。

大根堆

  所谓的大根堆即父节点的值总是比子节点的值大,即可以推出 A[i] >= A[i*2] ,A[i] >= A[i*2+1] 恒成立,可以看出,其实在上面所述的堆中所给的图就是一个大根堆。

对于一个大根堆,如何来维护某节点不小于其子节点?如图:

  若某节点并不与所想一样,即其比子节点小,那么我们必须对这个堆进行维护,正如图中所示,其过程为从该节点开始(对于此图而言,该节点为根节点),与其子节点进行比较,若不满足大根堆的条件,则将其与最大的数字所在节点进行交换,然后依次向下循环该过程,直到其不小于其子节点位置。

代码如下:

 1 void MaxHeapify(int* A,int heapSize,int index)
 2 {
 3     int l,r;
 4     int largest;//记录最大节点下标
 5     int tmp;
 6 
 7     largest = index;
 8     l = left(index);
 9     r = right(index);
10 
11     if((l <= heapSize) && (A[l] > A[index]))
12     {
13         largest = l;
14     }
15 
16     if((r <= heapSize) && (A[r] > A[largest]))
17     {
18         largest = r;
19     }
20 
21     if( largest != index)
22     {
23         tmp = A[largest];
24         A[largest] = A[index];
25         A[index] = tmp;
26         MaxHeapify(A,heapSize,largest);
27     }
28 }

建堆

  对于建立一个大根堆而言,对于我们得到的一个堆往往可能并不满足大根堆的条件,那么我们需要对其进行操作。

  除了根节点之外的任意节点的父节点为可表示为 parent(i) = i/2,那么可以得出从堆中的最后一个节点的父节点开始维护这个大根堆,直到维护到这个堆的根节点为止,大根堆便可建成。

代码如下:

1 void BuildMaxHeap(int* A,int heapSize)
2 {
3     for(int i = heapSize/2 ; i >= 1; i--)
4     {
5         MaxHeapify(A,heapSize,i);
6     }
7 }

堆排序

  大根堆的根节点往往是最大的,那么也就意味着说将根节点与最后一个节点交换,然后将最后一个节点排除在外,再次将堆调整成大根堆,循环此过程,直到这个堆中只包含根节点位置。大致过程如图所示:

 

代码如下:

 1 void HeapSort(int* A,int heapSize)
 2 {
 3     int tmp;
 4     for(int i = heapSize; i >= 2; i--)
 5     {
 6         tmp = A[i];
 7         A[i] = A[1];
 8         A[1] = tmp;
 9         heapSize--;//堆长度减1
10 
11         MaxHeapify(A,heapSize,1);
12     }
13 }

 

 

posted @ 2013-09-20 09:22  Howey  阅读(205)  评论(0编辑  收藏  举报