标签:cnt int 权值 堆排序 二叉树 磊磊 编号 打卡 节点
5.20
前言吐槽:
- 今天是5.20啦,但是作为单身修狗的我只能和代码过啦。。。继续加油算法打卡!!!
堆排序:
-
堆就是一棵完全二叉树
-
二叉堆是一种支持插入,删除,查询最值的数据结构。他其实是一棵满足"堆性质"的完全二叉树,树上的每个节点带有一个权值。若树中的任意一个节点的权值都小于等于其父节点的权值,则称该二叉树满足"大根堆性质”。若树中任意一个节点的权值都大于等于其父节点的权值,则称该二叉树满足"小根堆性质”。
-
这里采用一个数组来保存二叉堆。逐层从左到右为树中的节点依次编号,把此编号作为节点在数组中存储的位置(下标)。在这种存储方式中,父节点编号等于子节点编号除以2,左子节点编号等于父节点编号乘2,右子节点编号等于左子节点编号乘2加1;
-
题目链接:https://www.acwing.com/problem/content/description/840/
-
#include "iostream" using namespace std; const int N = 100010; int h[N], cnt; void down(int u) { // 这个模板的作用是父节点和其两个孩子节点的最小值,再交换父节点和这个最小值 int t = u; if (u * 2 <= cnt && h[u * 2] < h[t]) t = 2 * u; if (u * 2 + 1 <= cnt && h[u * 2 + 1] < h[t]) t = 2 * u + 1; if (u != t) { swap(h[u], h[t]); down(t); //每次这个t都是最小的哈 // 递归处理这个输入的值,直到它down到不能down为止,即整棵树又变成了一个小根堆. } } void up(int u) { while (u / 2 && h[u / 2] > h[u]) { swap(h[u], h[u / 2]); u /= 2; } } int main() { int n, m; cin >> n >> m; for (int i = 1; i <= n; i++) cin >> h[i]; cnt = n; /* cnt来存节点的最大下标,因为找左右孩子需要用2*u和2*u+1, 为了防止边界值问题,需要判断2*u < n,2*u+1<n; 并且,cnt也可以看成指向堆尾的一个指针。 */ for (int i = n / 2; i; i--) down(i); //初始化小根堆 // 用down函数将整棵树调整为一个小根堆 // 从2分之n开始down,建堆,时间复杂度为O(n) while (m--) { cout << h[1] << " "; h[1] = h[cnt--]; down(1); } }
标签:cnt,int,权值,堆排序,二叉树,磊磊,编号,打卡,节点 来源: https://www.cnblogs.com/gwl999/p/16294075.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。