堆排序的原理 以及堆的建立

堆的定义

堆的定义如下,n个关键字序列L[1....n]称为堆,当且仅当序列满足:

  1. L(i)>=L(2i)L(i)>=L(2i+1) (1<=i<=n/2)
    或者
  2. L(i)<=L(2i)L(i)<=L(2i+1) (1<=i<=n/2)

堆的性质与特点
可以将堆视为一颗完全二叉树,满足条件1的称为大根堆,大根堆的最大元素存放在根节点,且其任意一个非根结点的值小于等于其双亲结点值,满足条件2的称为小根堆,小根堆的定义刚好相反,根节点是最小元素。


如图所示为一个大根堆

建立堆的原理
本质上就是每个根节点跟其孩子结点比较,如果符号条件就交换,进行完一次以后,又与孩子的孩子结点进行比较,直至不再可以进行交换。

堆排序的原理
将堆顶元素与堆底元素进行交换,此时堆顶元素作为一个已经排好序的数放在堆数组的尾部,从这些未被排好序的元素重新建堆,在重复上述的过程,直到所有元素处理完。

大根堆的建立

  1. 检查当前结点是否满足 根>=左、右,若不满足,则将根与值更大的孩子结点进行交换。

  2. 若元素互换破坏了下一层的堆则采用相同的方式继续往下调整(小元素不断下坠)。

#include <bits/stdc++.h>
using namespace std;
int n, m;
int h[100005];
//--------调整堆的元素-------
void Heapadjust(int k, int len) {
//k为该根元素的下标
//若要建立小根堆 改相应符号即可
int tmp = h[k]; //tmp用来存这颗子树的根节点的值
for (int idx = k * 2; idx <= len; idx *= 2) { //乘以二原理是孩子的结点的下标
if (idx < len && h[idx] < h[idx + 1]) idx++; //大根堆拿更大的孩子去交换
if (h[idx] < tmp) break; //较大的孩子结点也小于根结点 说明不交换
h[k] = h[idx]; //交换
k = idx; //元素下坠,意思就是这一层的孩子结点作为下一层的根节点 继续去重复这个过程
}
h[k] = tmp; //最终的位置进行交换 (被筛选的结点值放入最终位置)
}
//--------建堆-------------
void Buildheap(int len ) {
for (int i = len / 2; i > 0; i-- ) {
Heapadjust(i, len);
}
}
//-------实现堆排序------------
void Heapsort(int len) {
Buildheap(len);//初始建堆
for (int i = len; i > 1; i--) { //n-1趟的交换和建堆过程
swap(h[i], h[1]);//和堆底元素交换
Heapadjust(1, i - 1);//调整,把剩余的i-1个元素整理成堆
}
}
int main() {
cin >> n >> m; //n个元素 输出前m小的数
for (int i = 1; i <= n; i++) cin >> h[i];
Buildheap(n);
for (int i = 1; i <= n; i++) cout << h[i] << " ";
cout << "\n";
Heapsort(n);
for (int i = 1; i <= m; i++) cout << h[i];
}

或者

可以使用c++函数make_heap(ve.begin(),ve.end(),less<int>() )
less<int>()对应大根堆 greater<int>()对应小根堆

#include <bits/stdc++.h>
using namespace std;
vector<int>h;
int n;
int main() {
cin >> n;
h.resize(n);
for (int i = 0; i < n; i++) cin >> h[i];
vector<int>a;
a = h;
make_heap(h.begin(), h.end()); //建立大根堆
cout << h[0];
for (int i = 1; i < n; i++) cout << " " << h[i];
cout << endl;
make_heap(a.begin(), a.end(), greater<int>());//建立小根堆
cout << a[0];
for (int i = 1; i < n; i++) cout << " " << a[i];
}

posted on   swj2529411658  阅读(51)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~

导航

< 2025年3月 >
23 24 25 26 27 28 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 1 2 3 4 5
点击右上角即可分享
微信分享提示