文章目录本文介绍了循环优先级队列的使用方法,代码由c语言实现,但了解相关思想后,使用c++、python等语言也可通过数组来快速实现循环优先级队列
- 前言
- 一、循环优先级队列是什么?
- 二、c语言实现
- 1.整体结构
- 2.函数实现
- 总结
前言
之前写了一篇使用c语言实现循环队列的,后来由于需要,个人又基于它实现了循环优先级队列。
一、循环优先级队列是什么?
之前所介绍的循环队列是先入先出的,很容易用平常的排队来理解。但如果这个队列要支持有紧急情况的人先出队呢?原先那种队列就不再适用了,我们就需要使用本文所提到的特殊队列–优先队列。
优先队列也是一种抽象数据类型。优先队列中的每个元素都有优先级,而优先级高(或者低)的将会先出队,而优先级相同的则按照其在优先队列中的顺序依次出队。
这样采用数组实现时,可以有两种方式,一种是以O(1)复杂度插入,每次在队尾入队,而以O(N)复杂度弹出最小元素;或者以O(N)复杂度插入,保持数组有序,而以O(1)复杂度删除。另一种则是使用堆来实现,堆可以认为是用数组实现的二叉树,可以在O(log N)的复杂度内实现元素的插入和删除。
在本文中采用的是第一种方式,即可在O(n)的时间复杂度内插入,O(1)的复杂度内弹出。
二、c语言实现 1.整体结构代码如下(示例):
#define QUEUE_SIZE (1024)
struct queue {
int data[QUEUE_SIZE];
int priority[QUEUE_SIZE];
int front;
int tail;
int empty;
};
void init(struct queue *);
void enqueue(struct queue *, int, int);
int dequeue(struct queue *);
同前述,data数组用于保存队列中数据,priority用于保存队列中各数据权重,priority值越小,越容先出队,front是队首元素索引,tail是队尾元素索引+1,empty表示队列是否为空。各函数的具体实现如下:
2.函数实现代码如下(示例):
#include "queue.h" #includevoid init(struct queue *q) { q->front = q->tail = 0; q->empty = 1; } // value表示要插入队列的元素的值,prio为其权重 void enqueue(struct queue *q, int value, int prio) { if (!q->empty && q->front == q->tail) { printf("queue shouldn't be overflown"); exit(-1); } q->empty = 0; int i = (q->tail - 1 + QUEUE_SIZE) % QUEUE_SIZE, j = q->tail, head = (q->front - 1 + QUEUE_SIZE ) % QUEUE_SIZE; // head为队首索引-1,当i==head,意味着队列中所有的元素都比较完毕 // i表示当前需要与value进行比较的元素的索引,j则为(i+1) % QUEUE_SIZE while( i != head) { if( q->priority[i] <= prio) break; q->data[j] = q->data[i]; q->priority[j] = q->priority[i]; j = i; i = (i - 1 + QUEUE_SIZE) % QUEUE_SIZE; } q->data[j] = value; q->priority[j] = prio; q->tail = (q->tail + 1) % QUEUE_SIZE; } int dequeue(struct queue *q) { if (q->empty) return -1; int value = q->data[q->front]; q->front = (q->front + 1) % QUEUE_SIZE; if (q->front == q->tail) q->empty = 1; return value; }
与循环队列改动较大的主要是enqueue函数,为实现插入后队列中的元素仍按权重保持有序,显然需要将入队元素插入在合适的位置中;函数中即按照这一思想,从队列尾开始,采用冒泡的方式,将priority值大的元素都向后挪一个单位
总结
以上就是循环队列c语言的简单实现,上述思想也可适用于像c++、java等,都可通过数组来快速实现简单的循环优先级队列



