优先队列-------队列

 优先队列的定义:

优先队列是一种特殊的队列数据结构,其中每个元素都有一个相关的优先级。在优先队列中,元素按照优先级的顺序被处理,具有最高优先级的元素先被处理,而具有较低优先级的元素则稍后被处理。优先队列可以是最大优先队列或最小优先队列,具体取决于优先级的定义方式。

 如图所示是优先队列的逻辑结构:

  

如图是优先队列的非逻辑结构:

其中的优先队列中的最大优先数为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;
}
运行结果:

                                                    

文章结束! 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值