堆以及堆排序详解

记录一下自己理解的堆和堆排序吧。

 

堆是一种类似于完全二叉树的树形结构,对于二叉树中所有非叶子节点,如果根节点的值严格大于其两个儿子的值,则称为

大顶堆,反之称为小顶堆。

 

堆排序的一般步骤:

  首先利用已有的数据构造一个堆,大顶堆增序,小顶堆降序。

  将堆顶的元素与堆末元素交换,接着重新调整剩下的元素为一个堆,直到堆末等于堆顶,则堆排序结束。

 

  如何把无序数组建堆。

  首先说明一个下沉调整法。

  言下之意就是对于一个节点,如果其存在值大于此节点值的儿子,就交换他们,并对这个儿子节点再进行调整。

  对于一个长度为n的无序数组,如果下标从1 ~ n,那么必定仅有n / 2个结点有子节点。我们从第n / 2个结点开始将其和前面

所有节点进行下沉调整,即得到一个堆。

 

大顶堆升序排序:

 

 1 #include <cstdio>
 2 using namespace std;
 3 
 4 const int maxn = 100 + 5;
 5 int val[maxn];
 6 
 7 void swap(int a, int b) {
 8     int t = val[a];
 9     val[a] = val[b];
10     val[b] = t;
11 }
12 
13 void sink(int n, int i) {
14     int max = i;
15     int l = i << 1, r = i << 1 | 1;
16     if(l <= n && val[l] > val[max]) max = l;
17     if(r <= n && val[r] > val[max]) max = r;
18     if(max != i) {
19         swap(max, i);
20         sink(n, max);
21     }
22 }
23 
24 void heap_sort(int n) {
25     for(int i = n / 2; i >= 1; i --) {
26         sink(n, i);
27     }
28     for(int i = n; i > 1; i --) {
29         swap(1, i);
30         //printf("%d %d\n", val[1], val[i]);
31         sink(i - 1, 1);
32     }
33 }
34 
35 int main() {
36     int n;
37     scanf("%d", &n);
38     for(int i = 1; i <= n; i ++) {
39         scanf("%d", &val[i]);
40     }
41     heap_sort(n);
42     for(int i = 1; i <= n; i ++) {
43         printf("%d ", val[i]);
44     }
45     puts("");
46     return 0;
47 }

 

小顶堆降序排序:

其实就是把sink函数中的大于号变成小于号了而已。

 1 #include <cstdio>
 2 using namespace std;
 3 
 4 const int maxn = 100 + 5;
 5 int val[maxn];
 6 
 7 void swap(int a, int b) {
 8     int t = val[a];
 9     val[a] = val[b];
10     val[b] = t;
11 }
12 
13 void sink(int n, int i) {
14     int min = i;
15     int l = i << 1, r = i << 1 | 1;
16     if(l <= n && val[l] < val[min]) min = l;
17     if(r <= n && val[r] < val[min]) min = r;
18     if(min != i) {
19         swap(min, i);
20         sink(n, min);
21     }
22 }
23 
24 void heap_sort(int n) {
25     for(int i = n / 2; i >= 1; i --) {
26         sink(n, i);
27     }
28     for(int i = n; i > 1; i --) {
29         swap(1, i);
30         sink(i - 1, 1);
31     }
32 }
33 
34 int main() {
35     int n;
36     scanf("%d", &n);
37     for(int i = 1; i <= n; i ++) {
38         scanf("%d", &val[i]);
39     }
40     heap_sort(n);
41     for(int i = 1; i <= n; i ++) {
42         printf("%d ", val[i]);
43     }
44     puts("");
45     return 0;
46 }

 

posted @ 2020-06-22 20:26  Cruel_King  阅读(228)  评论(0编辑  收藏  举报