一、什么是堆?
堆是一类树形的数据结构。分为大顶堆(最大堆)和小顶堆(最小堆)。
- 小顶堆的特点:儿子节点的值不小于父亲节点的值,堆顶元素是最小值
- 大顶堆的特点:儿子节点的值不大于父亲节点的值, 堆顶元素是最大值
堆可以被看做是一种完全二叉树结构。所以通常用数组实现,( 用指针也可以实现,比较麻烦)
二、小顶堆的实现
1、堆有两只操作:
①一种是压入(push)元素操作
②一种是压出(pop)堆顶元素操作
2、push操作:
这一操作,是将新的元素压入。压入一个元素很简单。 但是压入的同时,你还要维护它原来的特点, 否则就不叫堆了。
对于压入一个元素x的过程如下:
①暂时将这个元素x放到堆的最后一个节点编号的位置
②然后,跟父亲作比较,判断是否这个值x要向上浮(个人感觉这个浮很形象),同时他的父亲就要向下沉
③重复②直到,x不小于父亲的值。
3、pop操作:
这个操作也是, 压出堆顶很简单, 重要的是要维护它的状态,具体流程如下:
①将堆顶的值赋给r变量ret, 用于返回这个值
②将堆的最后一个元素x提到堆顶。
③然后就, 跟他的儿子比较, 判断是否这个值x要向下沉, 同时他的最小的那个儿子要向上浮
④重复③操作, 知道儿子的值不小于x。
#include<stdio.h>
#include<stdlib.h>
#define MAXN 50000
int heap[MAXN], sz = 0;// 堆数组, 和堆大小。
void push(int x)//压入堆操作。
{
int i = sz++;// i表示x开始要插入的位置
while(i > 0)//x的位置上限是0,所以i==0时,就停止操作
{
int p = (i - 1)/2; // p为 i的父亲的下标
if(x >= heap[p])break;// x 不小于 父亲的值就结束
//否沉则, 将父亲的值往下
heap[i] = heap[p];
i = p;// x的位置向上浮
}
heap[i] = x;// 将x的值 赋给它最终位置上。
}
int pop()
{
// 取出堆顶
int ret = heap[0];
int x = heap[--sz];// x是最后一个元素
int i = 0;// x的位置
while(i*2+1 <sz)
{
int l = i*2+1, r = i*2+2;// 左儿子 和右儿子
int min;
if(r < sz &&heap[r] < heap[l]) min = r;
else min = l;
if(heap[min] >= x)break;// 如果最小的那个儿子的值 不小于 x, 就结束
//否则
heap[i] = heap[min];// 最小的儿子向上浮
i = min;// x的位置向下沉
}
heap[i] = x;// 最终将x赋给 他所在的位置
return ret;
}
int main()
{
return 0;
}