堆以及堆排序详解
记录一下自己理解的堆和堆排序吧。
堆是一种类似于完全二叉树的树形结构,对于二叉树中所有非叶子节点,如果根节点的值严格大于其两个儿子的值,则称为
大顶堆,反之称为小顶堆。
堆排序的一般步骤:
首先利用已有的数据构造一个堆,大顶堆增序,小顶堆降序。
将堆顶的元素与堆末元素交换,接着重新调整剩下的元素为一个堆,直到堆末等于堆顶,则堆排序结束。
如何把无序数组建堆。
首先说明一个下沉调整法。
言下之意就是对于一个节点,如果其存在值大于此节点值的儿子,就交换他们,并对这个儿子节点再进行调整。
对于一个长度为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 }
时间并不会因为你的迷茫和迟疑而停留,就在你看这篇文章的同时,不知道有多少人在冥思苦想,在为算法废寝忘食,不知道有多少人在狂热地拍着代码,不知道又有多少提交一遍又一遍地刷新着OJ的status页面……
没有谁生来就是神牛,而千里之行,始于足下!
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步