堆排序
堆排序
堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序,它的最坏,最好,平均时间复杂度均为O(nlogn),它也是不稳定排序。首先简单了解下堆结构。
堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。
由于我们这里是把元素按照从小到大进行排序,所以我们选择大顶堆。这里我们数组下标从0开始,所以父结点和子结点有如下关系:a[i]>=a[2*i+1]&&a[i]>=a[2*i+2];
我们先看一下堆的修改操作(heapify),我们每次研究父结点和他的两个子结点,将最大的元素放到父结点上,然后递归整个过程。
我们建立一个堆(build_heap),只要找到最后一个非叶子结点也就是最后一个结点的父结点,然后不断进行堆的修改操作,这是一个从下向上滚动的过程,
我们再看一下堆排序的操作(heap_sort),我们建好一个大顶堆后,我们每次取得堆顶,然后交换堆顶和最后一个结点,然后砍掉最后一个结点,然后heapify这个过程。
附代码:
1 2 3 4 5 6 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
| #include<stdio.h> #include<algorithm> using namespace std; int tree[105]; void heapify(int n,int i) { if(i>=n) return ; int c1=i*2+1; int c2=i*2+2; int maxx=i; if(c1<n&&tree[c1]>tree[maxx]) { maxx=c1; } if(c2<n&&tree[c2]>tree[maxx]) { maxx=c2; } if(maxx!=i) { swap(tree[i],tree[maxx]); heapify(n,maxx); } } void build_heap(int tree[],int n) { int last_node=n-1; int parent=(last_node-1)/2; for(int i=parent; i>=0; i--) { heapify(n,i); } } void heap_sort(int n) { build_heap(tree,n); for(int i=n-1; i>=0; i--) { swap(tree[i],tree[0]); heapify(i,0); } } int main() { int n; scanf("%d",&n); for(int i=0; i<n; i++) { scanf("%d",&tree[i]); } heapify(n,0); for(int i=0; i<n; i++) { printf("%d\n",tree[i]); } return 0; }
|
附一组数据看一下整个排序过程
Input:
6
2 5 3 1 10 4
Output:
10 5 4 1 2 3
5 3 4 1 2 10
4 3 2 1 5 10
3 1 2 4 5 10
2 1 3 4 5 10
1 2 3 4 5 10