文章目录
一、堆的概念及性质结构
堆是一种非线性数据结构,本质上堆其实是一棵完全二叉树,通常存储在一维数组当中。将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。
堆具有的性质:
1.堆总是一棵完全二叉树;
2.堆中某个节点的值总是不大于或不小于其父亲节点的值;
对第二点的理解是:当堆为大根堆时,堆的根节点的值一定大于或等于其两个孩子节点的值;当堆为小根堆时,堆的根节点的值一定小于或等于其两个孩子节点的值
二、堆的实现
堆的存储结构是顺序表,堆的实现紧紧围绕着两个核心算法,即向上调整算法与向下调整算法。下面将分别从向上调整算法与向下调整算法展开,借助对堆的功能实现示例来分析这两种算法。首先展示堆的结构定义:
//定义Heap结构体
typedef struct Heap
{
int* a;
int size;//顺序表的长度
int capacity;//顺序表的容量
}HP;
1.向上调整算法
向上调整顾名思义即从下往上调整,从叶子节点开始向根节点的方向进行调整。
1)向上调整算法代码实现
基本的思想: (默认调整小堆)AdjustUp函数中形参child用来接收传入的孩子节点的下标,定义 parent变量来表示当前孩子的父亲节点的下标(由完全二叉树在数组中存储的性质得,parent=(child-1)/2 ,便可得到父亲节点的下标),通过比较 a[parent] 的值与 a[child] 的值,如果调整的是大堆则当
a[parent]>a[child] 时交换两值,如果调整的是小堆则当 a[parent] <a[child] 时交换两值。利用循环不断重复这一步骤,如果符合交换条件的就更新当前的child为parent,再将parent的下标更新一下,直到child走到根节点时停止,或者是当交换条件不符合时停止循环。
代码示例如下:
//交换函数
void Swap(int* a, int* b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
//a是存储堆的数组,child接收的是传入的孩子节点的下标
void AdjustUp(int* a, int child)
{
//完全二叉树的性质
int parent = (child - 1) / 2;
while (child > 0)
{
//调整小堆
if (a[child] < a[parent])
{
//交换两值
Swap(&a[child],&a[parent]);
//继续向上调整
child = parent;
parent = (child - 1) / 2;
}
else
{
break;
}