优先队列的定义:
优先队列是一种特殊的队列数据结构,其中每个元素都有一个相关的优先级。在优先队列中,元素按照优先级的顺序被处理,具有最高优先级的元素先被处理,而具有较低优先级的元素则稍后被处理。优先队列可以是最大优先队列或最小优先队列,具体取决于优先级的定义方式。
如图所示是优先队列的逻辑结构:
如图是优先队列的非逻辑结构:
其中的优先队列中的最大优先数为7 ,以后的每一次数据操作都会重新排列最大优先数。
代码实现优先队列(C语言):
一、创建一个结构体(用于表示队列中的节点):
typedef struct PriorityQueue{
int *__data,*data; //*__data表示用来调整队列起始下标的指针,*data表示存储数据的
int size,n; //size表示队列的最大存储数量,n表示队列中有多少个元素
}PriorityQueue;
二、定义一个宏(用于优化代码和实现特定功能):
#define ROOT 1
#define FATHER(i) ((i)/2) //父节点,若子节点排序i为2,3,则头节点为1
#define LEFT(i) ((i)*2) //左节点,排序为2*i
#define RIGHT(i) ((i)*2+1) //右节点,排序为2*i+1
#define cmp >
#define swap(a,b){ \ //交换a,b两个数据
printf("swap(%d,%d)\n",a,b); \ //打印a,b
__typeof(a) __c=(a);\ //将__c编译时检测跟类型a一样的数据类型,然后赋值
(a)=(b);\ //将b的值给a
(b)=__c;\ //c的值给b
}
//或者
//#define swap(a,b){ \
// printf("swap(%d,%d)\n",a,b); \
// a=a^b; \
// b=a^b; \
// a=a^b; \
//}
三、定义一个函数(初始化队列):
PriorityQueue *initPQ(int size){ //size为初始化队列的大小
PriorityQueue *p=(PriorityQueue *)malloc(sizeof(PriorityQueue)*size); //开辟存储空间
p->__data=(int *)malloc(sizeof(int)*size); //开辟存储空间
p->data=p->__data-ROOT; //当__data指针-1操作后,将不从0开始,若data从1开始,将是从__data的0开始
p->size=size; //初始化size
p->n=0; //初始化n
return p;
}
四、定义三个判断函数:
int empty(PriorityQueue *root){ //判空
return root->n==0;
}
int full(PriorityQueue *root){ //判满
return root->n==root->size;
}
int top(PriorityQueue *root){ //获取
return root->data[ROOT]; //头节点的值
}
五、 定义一个函数(用于插入数据):
int push(PriorityQueue *p,int x){ //x表示要插入的值
if(full(p))return 0; //判满
p->n+=1; //n+1代表队列中的元素个数加一
p->data[p->n]=x; //插入值
up_maintain(p->data,p->n); //向上调整,保证队列中的元素优先顺序
return 1;
}
六、定义一个函数(调整插入后的元素优先关系):
void up_maintain(int *data,int i){ //i代表要调整的元素位置下标
printf("\nup_maintain : %d",data[i]); //打印要调整的元素
while(i cmp ROOT&&data[i] cmp data[FATHER(i)]){ //i>1说明可以调整,后面的子节点大于父节点说明满足调整条件(3>2>1)
swap(data[i],data[FATHER(i)]); //交换父子节点的值
i=FATHER(i); //从目前的父节点开始,向上不断调整
}
printf("\n");
return;
}
七、定义一个函数(用于元素弹出操作):
int pop(PriorityQueue *root){
if(empty(root))return 0; //判空
root->data[ROOT]=root->data[root->n]; //堆的调整方式,将队列尾节点调到头节点
root->n-=1; //减1操作,代表队列中的元素减少
down_maintain(root->data,ROOT,root->n); //向下调整,保证队列中的元素优先顺序
return 1;
}
八、定义一个函数( 调整弹出后的元素优先关系):
void down_maintain(int *data,int i,int n){ //i表示位置,n表示队列中的元素总数
int ind; //用于存储最大元素值在队列中的下标值
printf("\ndown_maintain : %d",data[i]); //打印要调整的元素值
while(LEFT(i)<=n){ //先判断左节点
ind=i; //赋值
if(data[LEFT(i)] cmp data[ind]) ind=LEFT(i); //左节点更大,赋值
if(RIGHT(i)<=n && data[RIGHT(i)] cmp data[ind]){ //判断右节点且右节点更大
ind=RIGHT(i); //赋值
}
if(ind==i)break; //如果i等于ind,表示当前队列的排序正确
swap(data[i],data[ind]); //否则对不符合规则的元素进行交换
i=ind; //向下调整,在ind这个节点对其子节点进行调整
}
printf("\n");
return;
}
九、释放存储空间:
void clear(PriorityQueue *root){
if(root==NULL)return;
free(root->__data); //释放存储空间
free(root); //释放存储空间
return;
}
完整代码:
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define ROOT 1
#define FATHER(i) ((i)/2)
#define LEFT(i) ((i)*2)
#define RIGHT(i) ((i)*2+1)
#define cmp >
#define swap(a,b){ \
printf("swap(%d,%d)\n",a,b); \
__typeof(a) __c=(a);\
(a)=(b);\
(b)=__c;\
}
typedef struct PriorityQueue{
int *__data,*data;
int size,n;
}PriorityQueue;
PriorityQueue *initPQ(int size){
PriorityQueue *p=(PriorityQueue *)malloc(sizeof(PriorityQueue)*size);
p->__data=(int *)malloc(sizeof(int)*size);
p->data=p->__data-ROOT;
p->size=size;
p->n=0;
return p;
}
int empty(PriorityQueue *root){
return root->n==0;
}
int full(PriorityQueue *root){
return root->n==root->size;
}
int top(PriorityQueue *root){
return root->data[ROOT];
}
void down_maintain(int *data,int i,int n){
int ind;
printf("\ndown_maintain : %d",data[i]);
while(LEFT(i)<=n){
ind=i;
if(data[LEFT(i)] cmp data[ind]) ind=LEFT(i);
if(RIGHT(i)<=n && data[RIGHT(i)] cmp data[ind]){
ind=RIGHT(i);
}
if(ind==i)break;
swap(data[i],data[ind]);
i=ind;
}
printf("\n");
return;
}
int pop(PriorityQueue *root){
if(empty(root))return 0;
root->data[ROOT]=root->data[root->n];
root->n-=1;
down_maintain(root->data,ROOT,root->n);
return 1;
}
void up_maintain(int *data,int i){
printf("\nup_maintain : %d",data[i]);
while(i cmp ROOT&&data[i] cmp data[FATHER(i)]){
swap(data[i],data[FATHER(i)]);
i=FATHER(i);
}
printf("\n");
return;
}
int push(PriorityQueue *p,int x){
if(full(p))return 0;
p->n+=1;
p->data[p->n]=x;
up_maintain(p->data,p->n);
return 1;
}
void clear(PriorityQueue *root){
if(root==NULL)return;
free(root->__data);
free(root);
return;
}
void output(PriorityQueue *p){
printf("PQ(%d) : ",p->n);
for(int i=1;i<=p->n;i++){
printf("%d ",p->data[i]);
}
printf("\n");
return;
}
int main(){
srand(time(0));
PriorityQueue *p=initPQ(10);
int op,x;
while(~scanf("%d",&op)){
if(op==ROOT){
scanf("%d",&x);
printf("insert %d to PriorityQueue: \n",x);
push(p,x);
output(p);
}else{
printf("top : %d\n",top(p));
pop(p);
output(p);
}
}
clear(p);
return 0;
}
运行结果:
文章结束!