堆排序的原理 以及堆的建立
堆的定义
堆的定义如下,n个关键字序列\(L[1....n]\)称为堆,当且仅当序列满足:
- \(L(i)>=L(2i)\)且\(L(i)>=L(2i+1)\) \(\quad\) (\(1<=i<=n/2\))
或者 - \(L(i)<=L(2i)\)且\(L(i)<=L(2i+1)\) \(\quad\) (\(1<=i<=n/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 2024-11-01 23:33 swj2529411658 阅读(5) 评论(0) 编辑 收藏 举报