1、结构体和头文件:

#include<iostream>
#include<vector>using namespace std;struct MinHeap        //也可以不用结构体,直接用vector<int>
{vector<int> elem;int heapSize;MinHeap(vector<int> _elem){elem.insert(elem.begin(),_elem.begin(),_elem.end());heapSize = elem.size();} };

2、打印:

void printMinHeap(MinHeap heap,int i,int k)
{if(i < heap.heapSize){printMinHeap(heap,2*i+2,k+5);       //先打右子树 for(int j = 0; j < k; j++){cout<<" "; }cout<<heap.elem[i]<<endl;printMinHeap(heap,2*i+1,k+5);}
}

3、创建小根堆
将有n个结点的完全二叉树,从最后一个分支节点(n-1)/2自底向上自底向上、由局部到整体调整为小根堆,siftDown是自顶向下"筛选"调整算法

void createMinHeap(MinHeap &h)
{for(int i = (h.heapSize - 1)/2; i >= 0; i--){siftDown(h,i,h.heapSize-1);}
}

4、自顶向下"筛选"调整算法
从结点i开始到`m``为止,自上向下比较,如果子女的值小于双亲的值,则关键码小的上浮,继续向下层比较,否则不调整 ( 因为从最后一个分支结点开始构造小根堆,若结点i的子女比结点i的值大,则要么其左右子女是叶结点,要么是在前面被调整成了小根堆 )

int cnt = 1;
void siftDown(MinHeap& h,int i, int m)  //
{int temp = h.elem[i];         for(int j = i*2+1; j <= m; j = 2*j+1)   //j是i的左子女 {if(j < m && h.elem[j] > h.elem[j+1])  // j < m下标j+1在有效值内,{                      // h.elem[j]>h.elem[j+1]左子女大于右子女 j++;                    //根结点和右子女比较 } if(temp <= h.elem[j]) break;      //开始时的根结点小于等于左右子女则不需要调整 else    // temp > h.elem[j]      {   //开始时的根结点小于等于左右子女或者小于其子孙(第2次及以上循环时) h.elem[i] = h.elem[j]; //小的子女上移 i = j;                    // i 下降 }}h.elem[i] = temp;    //回放temp暂存的元素
}

5、创建的全部代码:

#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;struct MinHeap
{vector<int> elem;int heapSize;MinHeap(vector<int> _elem){elem.insert(elem.begin(),_elem.begin(),_elem.end());heapSize = elem.size();} };void printMinHeap(MinHeap heap,int i,int k)
{if(i < heap.heapSize){printMinHeap(heap,2*i+2,k+5);       //先打右子树 for(int j = 0; j < k; j++){cout<<" "; }cout<<heap.elem[i]<<endl;printMinHeap(heap,2*i+1,k+5);}
}
int cnt = 1;
void siftDown(MinHeap& h,int i, int m)  //自定向下"筛选"调整算法
{   //从结点i开始到m为止,自上向下比较,如果子女的值小于双亲的值,则关键码小的上浮//继续向下层比较,否则不调整(因为从最后一个分支结点开始构造小根堆,若结点i的子女比//结点i的值大,则要么其左右子女是叶结点,要么是在前面被调整成了小根堆 cout<<"第"<<cnt<<"次调整:(i == "<<i<<endl; printMinHeap(h,0,0);int temp = h.elem[i];         for(int j = i*2+1; j <= m; j = 2*j+1)   //j是i的左子女 {if(j < m && h.elem[j] > h.elem[j+1])  // j < m下标j+1在有效值内,{                      // h.elem[j]>h.elem[j+1]左子女大于右子女 j++;                    //根结点和右子女比较 } if(temp <= h.elem[j]) break;      //开始时的根结点小于等于左右子女则不需要调整 else    // temp > h.elem[j]      {   //开始时的根结点小于等于左右子女或者小于其子孙(第2次及以上循环时) h.elem[i] = h.elem[j]; //小的子女上移 i = j;                    // i 下降 }}h.elem[i] = temp;    //回放temp暂存的元素 cout<<"第"<<cnt++<<"次调整后:(i == "<<i<<endl; printMinHeap(h,0,0);cout<<endl;
}
void createMinHeap(MinHeap &h)
{//将一个数组自底向上、由局部到整体调整为小根堆, for(int i = (h.heapSize - 1)/2; i >= 0; i--){siftDown(h,i,h.heapSize-1);}
}
int main()
{vector<int> arr = {53,17,78,9,45,65,87,23};MinHeap heap(arr);createMinHeap(heap);printMinHeap(heap,0,0);return 0;
}

调试输出:

第1次调整:(i == 3)877865
534517923
第1次调整后:(i == 3)877865
534517923第2次调整:(i == 2)877865
534517923
第2次调整后:(i == 5)876578
534517923第3次调整:(i == 1)876578
534517923
第3次调整后:(i == 3)876578
534591723第4次调整:(i == 0)876578
534591723
第4次调整后:(i == 7)876578
945172353876578
945172353

6、插入新元素:
新结点总是插入到已经建成的小根堆的后面。因此,只要从最后一个结点沿它双亲的路径,自下向上比较,双亲比子女大,就和子女对调。

void insert(MinHeap &heap,int value)
{heap.elem.push_back(value);        //插在最后siftUp(heap,heap.elem.size());heap.heapSize++;
} void siftUp(MinHeap &heap,int start)
{ //从结点start开始到结点0为止,自下向上比较,如果子女的值小于双亲的值则双亲//的值下降,再用子女的值继续向上比较int temp = heap.elem[start];   //暂存新插入结点的值,用来跟双亲(祖先比较) int i = start;      // i指向子女 int j = (i-1)/2;  // j指向双亲while(i > 0){if(heap.elem[j] <= temp)    //双亲的值小不调整 {break;}else         //双亲的值大 {heap.elem[i] = heap.elem[j];  //双亲下移 i = j;              //i指向子女,i上升 j = (j-1)/2;        // j指向双亲} } heap.elem[i] = teap;     //存回子女
}

8、小根堆删除元素
删除一般是删除小根堆的最小元素,即其完全二叉树的顺序表示的第0号元素。

bool remove(MinHeap &heap,int &x)        //小根堆删除算法
{if(heap.heapSize == 0) return false; x = heap.elem[0];heap.elem[0] = heap.elem[heap.heapSize-1];   //最后元素填到补第一根结点 heap.elem.pop_back();heap.heapSize--;siftDown(heap,0,heap.heapSize-1);   //自上向下调整为小根堆 return true;       //删除成功
}

9、补充:
可以看出大小根堆的一个应用就是优先队列。

由一维数组创建小根堆相关推荐

  1. Pandas-数据结构-Series(一):创建Series【①由字典创建;②由一维数组创建;③由标量创建】【Series的属性:index、values、name】

    Pandas中一共有三种数据结构,分别为:Series.DataFrame和MultiIndex(老版本中叫Panel ).其中: Series是一维数据结构: DataFrame是二维的表格型数据结 ...

  2. MATLAB一维数组的创建与元素提取

    1.一维数组(向量)的创建 1.1直接输入法 从键盘直接输入元素,列与列之间的数据用逗号或空格分隔,行与行之间的数据用分号分隔. #生成列向量* a=[1;2;3] #生成列向量 b=[1,2,3] ...

  3. 算法自学__小根堆(Heap)

    参考资料: https://www.cnblogs.com/WindSun/p/11444446.html https://www.cnblogs.com/huashanqingzhu/p/11040 ...

  4. Numpy中数组创建函数的辨析

    首先推荐Numpy官方的教程,网址. 很多人会对数组创建函数的参数中什么时候要用括号np.zeros((2, 3)),什么时候不用括号np.eye(3, 5)感到疑惑,这里对它们统一进行梳理.(按照官 ...

  5. [转载] pandas中Series数组创建方法

    参考链接: 访问Pandas Series的元素 import numpy as np import pandas as pd ar = np.random.rand(5) # s = pd.Seri ...

  6. java二维数组的创建,java二维数组创建方法

    java动态创建二维数组,从零学java笔录-第31篇 图解二位数组在内存中存储,java二维数组动态赋值,java二维数组创建方法 二维数组的定义 type arrayName[ ][ ]; typ ...

  7. java 二维数组 的方法和属性_Java一维数组和二维数组详解(Java必备知识)

    数组是最为常见的一种数据结构,分为一级数组,二维数组以及多维数组.是把相同数据类型的元素,用一个标识符封装到一起的基本类型数据序列或对象序列. 目录 一维数组 创建一维数组 给一维数组赋值 获取数组的 ...

  8. c语言随机生成整数存放一维数组_文科生学 Python 系列 7: Numpy 数组/索引和切片...

    第四课:本课内容: • 0. 导入 NumPy 包 • 1. 创建 NumPy 数组 • 2. 索引和切片 • 3. 读取文件 • 4. 布尔型索引 • 5. 数组的运算 • 6. 常用函数举例 Nu ...

  9. 大根堆的删除c语言,小根堆大根堆的动态创建与堆顶元素删除

    堆的介绍与调整 本文主要是实现动态的创建一个堆,并且动态地向堆中插入元素,以及删除堆顶元素. 堆的创建与删除操作分为大根堆与小根堆两种实现. 头文件 #include #include #includ ...

最新文章

  1. 年终收藏!一文看尽2020年度最出圈AI论文合集
  2. 对Reformer的深入解读
  3. python中fib什么意思_Python斐波那契数列是什么?怎么用?
  4. 怎么查看电脑配置参数linux,linux下查看电脑配置
  5. vscode使用-添加格式化插件
  6. TestCenter中测试需求、测试用例、测试计划的评审方法
  7. python没有代码提示怎么设置_Python Kite 使用教程 轻量级代码提示
  8. Jeecg 初级入门
  9. 感觉Swagger功能不够强大?knife4j这款神器了解一下....
  10. loadrunner java 环境_java应用程序及服务器优化过程及loadrunner测试效果
  11. arduino 中断 串口_【Arduino教程】第一讲:Arduino是什么?
  12. 计算机软考做题app,计算机软考真题app
  13. 基于RRT算法的路径规划实现(matlab)
  14. 是女人,请进来学学拍照姿势!
  15. CentOS 安装Nvidia驱动+CUDA+cuDNN+Anaconda3
  16. python pip install一些第三方库的时候error
  17. 使用ajax传递数组
  18. android String文件中修改部分字体颜色
  19. 计算机操作系统的阶段分为几个阶段,浅谈操作系统的发展历程
  20. matlab下载mingw64以及配置方法

热门文章

  1. python软件下载3版本-【python3下载】python3下载安装 中文版-七喜软件园
  2. python有什么用-我们为什么要选择学习python?学习python有什么用?
  3. python骗局-老码农冒死揭开真相:quot;别吹了,Python无用!”
  4. 如何自学python知乎-马哥教育官网-专业Linux培训班,Python培训机构
  5. python入门指南 许半仙txt-影帝的脑子坏了
  6. 友达以上恋人未满 体验博越G-Netlink系统
  7. 同时支持mp4/ogg/webm/flv格式的视频播放
  8. 移动web-双飞翼(圣杯)布局
  9. 【java笔记】IDEA debug调试
  10. LeetCode 437. 路径总和 III