堆排序以及C++实现

参考博客:

https://www.cnblogs.com/lanhaicode/p/10546257.html

https://www.cnblogs.com/woxiaosade/p/10628388.html

 

一. 堆的概念

堆是一种非线性结构,可以把堆看作一个数组,也可以被看作一个完全二叉树,通俗来讲堆其实就是利用完全二叉树的结构来维护的一维数组

按照堆的特点可以把堆分为大顶堆小顶堆

大顶堆:每个结点的值都大于等于其左右孩子结点的值

小顶堆:每个结点的值都小于等于其左右孩子结点的值

(堆的这种特性非常的有用,堆常常被当做优先队列使用,因为可以快速的访问到“最重要”的元素)

 

 

我们对堆中的结点按层进行编号,将这种逻辑结构映射到数组中就是下面这个样子

大顶堆:arr[i] >= arr[2i+1] && arr[i] >= arr[2i+2] 

小顶堆:arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2] 

 

二. 创建堆

下为从一个数组创建一个大顶堆的例子:

给定数组{0,1,2,3,4,5,6,7,8,9},先依次创建一个完全二叉树:

 

 然后,大顶堆从底层向上层搜索,3[7][8]这个节点因为8最大,交换8和3,同理交换4和9

 

 再然后,交换倒数第二层的元素1和9,6和2,交换完,看下一层,发现1和4需要交换:

 

 然后,检查最上层,交换0和9,再看第二层,交换0和8,然后检查最后一层,0和7需要交换

 

 自此,一个大顶堆构建完成,顺便分享在线画二叉树的网站:

http://mshang.ca/syntree/

 

C++中,std::make_leap() 可以用来创建堆,默认第三个参数为 std::less<int>(),即创建大顶堆,改成std::greater<int>()可以创建小顶堆

示例:

复制代码
 1 #include <iostream>
 2 #include <vector>
 3 #include <algorithm>
 4 using namespace std;
 5 
 6 int main() 
 7 {
 8     vector<int> q;
 9     for (int i = 0; i < 10; i++) {
10         q.push_back(i);
11     }
12     make_heap(q.begin(), q.end(), less<int>());
13     for (int i = 0; i < q.size(); i++){
14         cout << q[i] << " ";
15     }
16     cout << endl;
17     return 0;
18 }
19 
20 //Output: 9 8 6 7 4 5 2 0 3 1
复制代码

 

三. C++中堆的其它操作

std::pop_heap 

用于将堆的第零个元素与最后一个元素交换位置,然后针对前n - 1个元素调用make_heap()函数,它也有三个参数,参数意义与make_heap()相同,第三个参数应与make_heap时的第三个参数保持一致。

注意:pop_heap()函数,只是交换了两个数据的位置,如果需要弹出这个数据,请记得在pop_heap()后加上q.pop_back();

示例:

复制代码
 1 #include <iostream>
 2 #include <vector>
 3 #include <algorithm>
 4 using namespace std;
 5 
 6 int main() 
 7 {
 8     vector<int> q;
 9     for (int i = 0; i < 10; i++) {
10         q.push_back(i);
11     }
12     make_heap(q.begin(), q.end(), less<int>());
13     pop_heap(q.begin(), q.end(), less<int>());
14     for (int i = 0; i < q.size(); i++) {
15         cout << q[i] << " ";
16     }
17     cout << endl;
18     return 0;
19 }
20 
21 //Output: 8 7 6 3 4 5 2 0 1 9
复制代码

std::push_heap

push_heap()用于把数据插入到堆中,它也有三个参数,其意义与make_heap()的相同,第三个参数应与make_heap时的第三个参数保持一致。

在使用push_heap()前,请确保已经把数据通过q.push_back()传入q中,而不是在push_heap()后再使用q.push_back(t)!!

 示例:

复制代码
 1 #include <iostream>
 2 #include <vector>
 3 #include <algorithm>
 4 using namespace std;
 5 
 6 int main() 
 7 {
 8     vector<int> q;
 9     for (int i = 0; i < 10; i++) {
10         q.push_back(i);
11     }
12     make_heap(q.begin(), q.end(), less<int>());
13     q.push_back(10);
14     push_heap(q.begin(), q.end(), less<int>());
15     for (int i = 0; i < q.size(); i++) {
16         cout << q[i] << " ";
17     }
18     cout << endl;
19     return 0;
20 }
复制代码

插入后结果变为:

10 9 6 7 8 5 2 0 3 1 4

std::sort_heap

将heap进行堆排序

上例排序后结果为:1 2 3 4 5 6 7 8 9

堆排序的原理:

将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值,如此反复执行,便能得到一个有序序列了。

pseudo code:

 

 

升序----使用大顶堆

降序----使用小顶堆

 

四. 典型应用

经典例题:输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4。

利用堆顶最大的原理解决这个问题。

复制代码
 1 vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
 2         int len=input.size();
 3         if(k<1||k>len) return vector<int>();
 4 
 5         vector<int> res(input.begin(),input.begin()+k);//左闭右开input.begin()+k是res.end()的位置
 6         //建堆(默认最大堆)
 7         make_heap(res.begin(),res.end());
 8 
 9         for(int i=k;i<len;i++)
10         {
11             if(input[i]<res[0])
12             {
13                 //先pop,然后在容器中删除
14                 pop_heap(res.begin(),res.end());
15                 res.pop_back();
16                 //先在容器中加入,再push
17                 res.push_back(input[i]);
18                 push_heap(res.begin(),res.end());
19             }
20         }
21         //使其从小到大输出
22         sort_heap(res.begin(),res.end());
23 
24         return res;
25 
26     }
复制代码

 

posted @   Asp1rant  阅读(264)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示