HappyCpp

一个不会打代码的程序猿

0%

堆排序

堆排序

堆排序

堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序,它的最坏,最好,平均时间复杂度均为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);
//build_heap(tree,n);
//heap_sort(n);
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