所谓的优先队列通俗点讲就是,当我们处理一些事情的时候我们通常会先处理比较重要或者需要处理的时间比较短的事情,而这个优先队列实现的就是这个思想,我们通过采取二叉搜索树的方式来进行实现二叉堆(数组实现)。学过二叉树的我们一定应该知道在一颗二叉树中一个结点X(根节点除外)所在的位置为i,那么他的父节点所在位置为i/2,左孩子为i*2,有孩子为i*2+1。由此性质,我们完全可以用数组来实现。
如果只是阐述这种概念我们完全可以理解,但是在代码的实际操作中并不是,因为我们并不能决定用户处理事情是否会排好序在应用我们的程序,所以我们要时刻保持我们的优先队列满足结构性和堆序性两个性质,缺一不可。当我们进行插入的时候如果该值比某个节点小,那我们就需要把那个结点进行向下移动,在进行插入,这个叫做上滤。 如果我们要进行对第一个元素进行出队,那我们就需要把相对较小的树向上移动,这个叫下滤。
下面我们直接看代码,代码逻辑很清晰,完全可以理解。对队列不太明白的可以看我之前介绍队列的文章。
#include <stdio.h>
#include <stdlib.h>
//定义最小值,保证队列的头结点值为最小
#define MinData 1 << 31
//定义数据类型,为了方便演示这里用int
typedef int ElemType;
//定义优先队列存储结构
typedef struct Queue
{
//该队列的最大容量
int capacity;
//该队列目前以存在的元素的个数
int size;
//元素数组
ElemType *data;
}Component, *ProQueue;
//对队列进行初始化
ProQueue Initialization(int capacity)
{
ProQueue queue = (ProQueue)malloc(sizeof(Component));
queue -> data = (ElemType *)malloc(sizeof(ElemType) * (capacity + 1));
queue -> capacity = capacity + 1;
queue -> size = 0;
queue -> data[0] = MinData;
return queue;
}
//插入元素
void Insert(ProQueue queue, ElemType data)
{
if(queue -> capacity == queue -> size + 1)
{
return;
}
int pointer = ++queue -> size;
for(pointer; data < queue -> data[pointer / 2]; pointer /= 2)
{
queue -> data[pointer] = queue -> data[pointer / 2];
}
queue -> data[pointer] = data;
}
//删除最小元素,其实就是出列,要保持优先队列的结构性和堆序性
ElemType DeleteMin(ProQueue queue)
{
if(queue -> size == 0)
{
return NULL;
}
//获取队列最大值
ElemType maxData = queue -> data[queue -> size];
//获取队列最小值
ElemType minData = queue -> data[1];
//定义队列指针
int pointer = 1;
//定义左孩子指针
int child;
for(pointer; pointer * 2 < queue -> size; pointer = child)
{
child = pointer * 2;
if(child < queue -> size && queue -> data[child] > queue -> data[child + 1])
{
child++;
}
queue -> data[pointer] = queue -> data[child];
}
queue -> data[pointer] = maxData;
queue -> data[queue -> size] = NULL;
queue -> size--;
return minData;
}
int main(void)
{
ProQueue queue = Initialization(20);
printf("%d\n", queue -> data[0]);
Insert(queue, 10);
Insert(queue, 16);
Insert(queue, 18);
Insert(queue, 7);
printf("%d\n", queue -> data[1]);
ElemType e = DeleteMin(queue);
printf("%d\n", e);
printf("%d\n", queue -> data[1]);
return 0;
}