堆,堆排序

简介: 堆,堆排序

堆是一棵完全二叉树,如果其父亲结点的值均比孩子结点大,称大顶堆,反之称为小顶堆,学过数据结构知道用数组表示完全二叉树最为简便,自然而然,我们这里也就用数组来表示堆。

如果数组是从序号1开始,对一棵完全二叉树,下列点如果存在,则对结点i/2是父亲结点,2i和2i+1是左右孩子结点。


1.堆


以建大顶堆为例:

建堆过程可以通过比赛规则来模拟,两两对决决出一个强者,强者再对决…最后在最顶上的就是最强者,这样形成的完全二叉树可以保证每一个父亲结点比其下面的孩子结点要强,只要我们保证所有父亲结点满足上述条件就可以了,而在保证每一个父亲结点是不是最大时,自然要和他下面的孩子结点比,这样由上相下比就是一个向下调整的过程,这个过程会重复多次,不妨先建立一个向下调整的函数

void downadjust(int low,int n){   //向下调整操作 ,low为父亲结点,共n个元素
  int p=2*low;
  while(p<=n){                        
    int temp=p;
    if(p<n&&heap[p]<heap[p+1])temp=p+1;        //找出孩子较大个
    if(heap[p/2]<heap[temp])                  //没有它大,调下去
    {
    swap(heap[p/2],heap[temp]);
    p=temp*2;
    }
    else {
    break;}
  } 
}

现在考虑建堆,完全二叉树的父亲结点共n/2个,只要对这些结点向下调整即可,唯一值得思考是从第一个开始还是从最后一个开始,实际上面的那个向下调整函数是默认下面是大根堆的(思考一下为什么),所以自然是从最后一个父亲结点开始。

void createheap(int n) {                               //建立大根堆 
  for(int i=n/2;i>=1;i--)
  downadjust(i,n);
}

建堆完成后考虑一下删除元素和加入元素,删除最大元素的话,只要把最后一个元素发在堆顶,视堆共n-1,个元素进行一次向下调整即可。

那如何加入元素呢?这里我们直接把元素放在最后一位,对比向下调整,我们来一次向上调整即可。

void upadjust(int n) {     //向上调整操作
   int temp=n/2;
   while(temp>=1){
    if(heap[n]>heap[temp]){
      swap(heap[n],heap[temp]);
    n=temp;
    temp=n/2;
     }
    else{break;} 
   }  
}

2.堆排序


堆排序实际是一种选择排序,正是利用了堆,选择效率比简单选择排序快了许多,我们可以利用大根堆每次把最大元素选出来,放在数列末尾,有点类似于堆删除元素,重复n-1次:

void heapsort(int n){
  createheap(n);
  for(int i=n;i>1;i--)
  {
    swap(heap[1],heap[i]);
    downadjust(1,i-1);
  } 
}

最后附完整的编程代码:


#include <iostream>
#include<algorithm>
using namespace std;
const int maxn=101;
int heap[maxn];
void downadjust(int low,int n){                            //向下调整操作 
  int p=2*low;
  while(p<=n){
    int temp=p;
    if(p<n&&heap[p]<heap[p+1])temp=p+1;           //大根 
    if(heap[p/2]<heap[temp])
    {
    swap(heap[p/2],heap[temp]);
    p=temp*2;
    }
    else {
    break;}
  } 
}
void upadjust(int n) {
   int temp=n/2;
   while(temp>=1){
    if(heap[n]>heap[temp]){
      swap(heap[n],heap[temp]);
    n=temp;
    temp=n/2;
     }
    else{break;} 
   }  
}
void createheap(int n) {                               //建立大根堆 
  for(int i=n/2;i>=1;i--)
  downadjust(i,n);
}
void heapsort(int n){
  createheap(n);
  for(int i=n;i>1;i--)
  {
    swap(heap[1],heap[i]);
    downadjust(1,i-1);
  } 
}
int main(){
  heap[1]=6;
  heap[2]=9;
  heap[3]=1;
  heap[4]=5;
  heap[5]=9;
  heapsort(5);
  for(int i=1;i<=5;i++)
  cout<<heap[i]<<" ";
  return 0;
}
相关文章
数字频带传输——二进制数字调制及MATLAB仿真
数字频带传输——二进制数字调制及MATLAB仿真
987 1
|
1月前
|
人工智能 机器人 数据处理
ICLR2026 !SAM3重磅来袭:能“听懂人话”的分割模型,性能狂飙2倍
Lab4AI.cn覆盖全周期科研支撑平台,提供论文速递、AI翻译和AI导读工具辅助论文阅读;支持投稿论文复现和Github项目复现,动手复现感兴趣的论文;论文复现完成后,您可基于您的思路和想法,开启论文创新与成果转化。
457 6
|
缓存
IDEA找不到或无法加载主类
IDEA找不到或无法加载主类
4144 0
IDEA找不到或无法加载主类
|
3月前
|
Web App开发 人工智能 自然语言处理
快速搞定Dify+Chrome MCP:打造能操作网页的AI助手
本文介绍了如何通过Dify和Chrome MCP在3分钟内打造一个能操作浏览器的AI助手。结合Dify的LLM能力与Chrome MCP的浏览器控制功能,用户可用自然语言指令让AI自动填写表单、抓取数据、点击按钮,实现网页自动化操作。无需复杂编程,适合本地部署,可应用于数据监控、内容抓取等多种场景。
|
9月前
|
消息中间件 关系型数据库 MySQL
基于 Flink CDC YAML 的 MySQL 到 Kafka 流式数据集成
基于 Flink CDC YAML 的 MySQL 到 Kafka 流式数据集成
986 0
|
机器学习/深度学习 自然语言处理 搜索推荐
深度学习中的多头注意力机制及其应用探索
深度学习中的多头注意力机制及其应用探索
941 2
|
12月前
|
网络协议 安全 网络虚拟化
openvpn-as的三种安装方式
OpenVPN 是一个开源的VPN软件包,支持多种操作系统,可创建基于SSL/TLS的安全隧道。它分为社区版
2460 2
|
Windows
苹果笔记本如何安装windows系统
苹果笔记本如何安装windows系统
1631 1
|
存储 前端开发 JavaScript
从 Web 2.0 到 Web 3.0:前端开发的历史与未来
【10月更文挑战第4天】本文探讨了从 Web 2.0 到 Web 3.0 的前端开发演变过程。Web 2.0 时代,前端开发者从静态网页设计走向复杂交互,技术框架如 jQuery、React 和 Vue 带来了巨大的变革。而 Web 3.0 以区块链技术为核心,带来了去中心化的互联网体验,前端开发者面临与区块链交互、去中心化身份验证、分布式存储等新挑战。文章总结了 Web 2.0 和 Web 3.0 的核心区别,并为开发者提供了如何应对新技术的建议,帮助他们在新时代中掌握技能、设计更安全的用户体验。
440 0
从 Web 2.0 到 Web 3.0:前端开发的历史与未来
|
缓存 自然语言处理 JavaScript
Thinkphp6安装
Thinkphp6安装
272 0