优先队列PriorityQueue C语言实现

本文详细介绍了如何使用C语言实现优先队列PriorityQueue,包括基础知识、堆的概念,以及优先队列的创建、判空、判满、插入、查找最值、删除和摧毁等操作。通过实例展示了插入和删除过程,以及完整的C代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

基础知识


  • 堆是用数组实现的二叉树,它的逻辑结构是二叉树,存储结构是数组,所以它没有左右孩子指针。
    堆(优先队列)的结构体定义为:
#define Type int 
typedef struct HeapStruct{
   
	int capacity; 
	int size;
	Type *eles; 
}PriorityQueue;

堆的存储结构
capacity是堆的最大容量,创建时进行初始化;size是已使用的容量;eles是指针,用于对数据进行操作.

  • 优先队列
    优先队列是利用堆的性质实现的,分两种情况,大顶堆小顶堆。以大顶堆为例,其性质是:

    1. 节点的左右孩子的值,都小于该节点的值
    2. 左右孩子也都是大顶堆.

    根据优先队列的性质可以看到,大顶堆的根节点即为序列的最大值,相应的小顶堆的根节点就是序列的最小值。那么我们将一组数输入到大顶堆中,然后依次输出根节点,便实现了堆排序,这样的堆就是常用的优先队列(PriorityQueue)。
    这个过程中,我们主要做的是,每插入一个元素,都要将堆调整为优先队列,同样,每删除一个根节点,也要将堆重新调整。

构建优先队列

优先队列的操作包括:

  1. 创建/初始化
  2. 判空/判满
  3. 插入
  4. 查找最值
  5. 删除
  6. 摧毁

创建

创建一个PriorityQueue结构体,并分配相应的内存,为指针eles分配capacity+1的内存。因为用数组来存储二叉树,父节点和子节点存储位置的关系是son = father/2,在插入操作中,从叶节点创建一个空穴,不断和父节点比较并上移,所以从子节点到父节点经常要取半i/2,为了操作方便,我们把数组的0号位置空出来不使用,将根节点放在i=1的位置上,因此在初始化时,分配capacity+1的内存。

PriorityQueue *init(int max_size){
    //这里初始化init定义为指针函数,其返回值是指针,可以直接赋值给*pq 
	PriorityQueue *pq = NULL; //pq为结构体指针
	//检查输入大小的合法性 
	if(max_size <= 0){
   
		printf("max_size is illeagel!\n");
		return NULL;		
	} 
	pq = malloc(sizeof(PriorityQueue));
	
	if(pq == NULL){
   
		printf("malloc failed!\n");
		return NULL;
	}
	//下标为0的位置保留,不使用 
	pq->eles = malloc((max_size+1)*sizeof(Type));//为数组eles分配max_size + 1的内存
	if(pq->eles == NULL){
   
		printf("eles malloc failed!\n");
		free(pq);
		return NULL;
	}
	
	//初始化队列成员
	memset(pq->eles, 0, (max_size+1)*sizeof(Type));
	pq->capacity = max_size;
	pq->size = 0;
	 
	return pq;
}

在使用时只需要

PriorityQueue *pq = init(max_size);

判空

//判断是否为空
int is_empty(PriorityQueue *pq){
   
	if(pq == NULL) //如果指针为空
		return 0;
	if(pq->size == 0)
		return 1;
	else
		return 0; 
}

判满

//判断是否为满
int is_full(PriorityQueue *pq){
   
	if(pq == NULL)
		return 0;
	if(pq->size == pq->capacity)
		return 1;
	else
		return 0;
}

插入

我们在 i = size +1 的位置创建一个空穴,要插入的值value与父节点进行比较,如果大于父节点,刚将父节点与空穴交换,此时空穴的位置到了 i/2 ,然后重复上述步骤,直到 i <= 1 或value小于父节点为止,然后将value 放入到空穴里,即完成了插入操作。
以序列3, 4,7,5,8,2 为例,令capacity = 9。

  • 插入3
    插入3
  • 插入4
    插入4
    空穴与其父节点 j/2 进行比较,即 4 > 3,所以父节点与3交换,j = j/2,因为 j = 1,所以操作终止,将4放入空穴 j = 1;size = size + 1;
    插入4
  • 插入7
    插入7
    在这里插入图片描述
    在这里插入图片描述
    以此类推。最终的结果为
    插入结果
    序列在数组中的存储并不是有序的,直接遍历不能得到有序序列,因为它在结构上是树形的,类似于二叉树的顺序存储结构。
    插入操作的完整代码如下:
int push(Type value, PriorityQueue *pq){
   
	int i=0;
	 
	//首先判断队列是否为满 
	if(is_full(pq)){
   
		printf("Queue is Full!\n");
		return 0;
	
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值