堆的概念及其基本操作图解
堆是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵树的数组对象。堆总是满足下列性质:
- 堆中的某个节点的值总是不大于或不小于其父节点的值(不大于则为大根堆,不小于则为小根堆)
- 堆总是一棵完全二叉树、
基础操作
先说一下 c++ 标准库 STL 中有一个神奇东西叫做优先队列(priority_queue),它可以很方便地实现一些基础的堆操作。
#include<queue> //头文件
using namespace std;
priority_queue<int>q; //定义一个大根堆 priority_queue<int,vector<int>,greater<int> >q1; //定义一个小根堆 q.push(x);//将x放进堆里
q.top(); //取出堆的堆顶元素,不删除
q.empty(); //判断堆是否为空,为空是true,不为空是false
q.pop(); //删除堆顶元素
其他具体操作自行百度
插入操作
当插入一个新值时,首先将值放到树的最后的位置。
然后将这个值与父元素比较,如果不满足性质1,则与父元素替换(如下图所示)。
- 第一步
- 第二步
- 第三步
### 取最小值操作
在最小堆中,拿出一个最小值,当然就是拿出第一个数啦~不过拿完以后树不就没有“头”了?
不用担心,我们可以把最后一个数放到头的位置,这样树的结构就不会改变,而且操作简单(因为是最后一个数)。
当然,因为是最后一个数,必然会出现不满足条件1的情况,所以我们需要把新的树头与子元素比较替换,下面是图片演示:
假设我们有一个原始的最小堆如下所示,接下来我们要取最小值:
>>>>>
不过交换完很可能是不满足性质1的,那么我们就需要比较替换,替换规则是和两个子元素中最小的一个替换
由图可知,在取值操作中,交换次数最大也为树的高度(log n)
堆的排序
我们知道了如何取最小值,那么堆的排序简单啦~只要依次取堆的最小值,那么当堆取完时,我们取出的数据不就是一个从小到大的序列嘛!