堆排序

  堆排序是我们熟知的常用的排序算法。

  首先先介绍一下什么是堆排序。堆指的并不是我们数据结构上分配内存的堆栈,在这里指的是大顶堆和小顶堆。大顶堆是指根节点数值大于左右孩子节点的完全二叉树,也有可能是满二叉树。总之,就是一颗存贮数值的树。我们可以利用根节点大于孩子节点这一特性对一组数组建立堆,不断取出根节点再建立大顶堆的过程来完成对数组排序。

  对于大顶堆,可以用这样的数学角度考虑,即a[i]>a[2i],且a[i]>a[2i+1],也就是上面所说的根节点的数值大于左右孩子节点的数值。对于小顶堆则反之。

  知道了大顶堆的概念,如何建立大顶堆呢?可以这样考虑。大顶堆父亲节点肯定大于孩子节点,所以首先对一个节点与其左右孩子节点比较,选取数值最大的那个,交换数值变成大顶堆。如果过程中交换了数值,说明被交换的那个孩子还需要再对其考虑一次是否为大顶堆,再对它进行一次比较。如此一来,我们完全可以利用递归调用自身的方式进行建堆。

  上面的第一步只是保证那一部分是大顶堆,如何保证整棵树都是大顶堆的形式?这就需要我们把每一个非叶子节点比较一次。但是按照什么样的顺序呢?为了保证整个树为大顶堆,这就需要我们从下而上建立大顶堆。请你自己思考一下这是为什么。也就是从n/2(n指的是总长度)到1逐个比较排序建堆。当然,对于叶子节点根本无需考虑,因为总之它的父母会主动和他们比较。

  以上两步工作是完成建立大顶堆,可是我们的堆排序呢?接下来,我们就是巧妙的利用大顶堆的性质,对数组进行交换排序。具体操作为:首先交换a[0]和a[n],即交换最大的到最后。然后再把剩余的1到n-1的堆重新进行堆排序。反复循环。这样就可以保证堆的第一个元素永远是最大的。不断交换第一个元素与最后一个,完成从小到大排序。

  十分简单而又十分优雅的排序,但是我习惯上用0作为数组的第一个下标,所以各种下标处理就需要格外谨慎。左右孩子节点处理也要十分小心。已下为具体的C++程序代码,CB已经完美运行。

 1 #include<iostream>
 2 using namespace std;
 3 
 4 int a[10] = {4,1,3,2,16,9,10,14,8,7};
 5 int len = sizeof(a)/sizeof(int);
 6 
 7 inline int PARENT(int i){
 8     return i/2;
 9 }
10 
11 inline int LEFT(int i){
12     return 2*i+1;
13 }
14 
15 inline int RIGHT(int i){
16     return 2*i+2;
17 }
18 
19 void exchange(int &a, int &b){
20     int temp = a;
21     a = b;
22     b = temp;
23 }
24 
25 void maxHeapify(int a[], int i){    //put the index i into the right place
26     int maxIndex;
27     if(LEFT(i) < len && a[LEFT(i)] > a[i]){
28         maxIndex = LEFT(i);
29     }else{
30         maxIndex = i;
31     }
32     if(RIGHT(i) < len && a[RIGHT(i)] > a[maxIndex]){
33         maxIndex = RIGHT(i);
34     }
35 
36     if(maxIndex != i){
37         exchange(a[i], a[maxIndex]);
38         maxHeapify(a, maxIndex);
39     }
40 }
41 
42 void buildMaxHeap(int a[]){
43     int l;
44     if(len%2 == 0)
45         l = len/2 - 1;
46     else
47         l = len/2;
48     for(int i = l; i >= 0; --i)
49         maxHeapify(a, i);
50 }
51 
52 void heapSort(int a[]) {
53     buildMaxHeap(a);
54     for(int i = len - 1; i != 0; --i){
55         exchange(a[0], a[i]);
56         --len;
57         buildMaxHeap(a);
58     }
59 }
60 int main() {
61     buildMaxHeap(a);
62     for(int i = 0; i < 10; ++i)
63         cout<<a[i]<<" ";
64     cout<<endl;
65     heapSort(a);
66     for(int i = 0; i < 10; ++i)
67         cout<<a[i]<<" ";
68 
69     return 0;
70 }

 

posted @ 2016-01-27 19:05  VF_Ever  阅读(248)  评论(0编辑  收藏  举报