数据结构算法之优先级队列

故事的引入

话不多说先copy一张图片

英雄联盟游戏里面防御塔都有一个自动攻击功能,小兵排着队进入防御塔的攻击范围,防御塔先 攻击靠得最近的小兵,这时候大炮车的优先级更高(因为系统判定大炮车对于防御塔的威胁更大), 所以防御塔会优先攻击大炮车。而当大炮车阵亡,剩下的全部都是普通小兵,这时候离得近的优 先级越高,防御塔优先攻击距离更近的小兵。
在这里插入图片描述

优先级队列和普通队列的区别是,就是在数据区域加权了一个priority的结点,这个结点的作用就是一个权值。根据这个这个权值来确定出队列的先后顺序

魔杖为营,武刃所灭.好的上代码:
//这里我们进行队列出列的操作的时候用到了二级指针,这个地方也是用到了linux内核中的队列出队方式。
//二级指针 **prev

#include<stdio.h>
#include<Windows.h>

typedef int dateType;
#define MAX_SIZE 5


typedef struct _Node{
    
    
	dateType data;
	int prority;
	_Node *next;
}Node;

typedef struct _Queue{
    
    
	Node *front;
	Node *rear;
	int length;

}Queue;

//1、队列初始化
bool initQueue(Queue *Q){
    
    
	

	if(!Q) return false;
	Q->front = NULL;
	Q->rear = NULL;
	Q->length = 0;
	return true;

}

//2、判断队列是否为空
bool isEmpty(Queue *Q){
    
    
	
	if(Q->length==0) return true;
	
	return false;

}
//3、判断队列是否已满

bool isFully(Queue *Q){
    
    
	
	if(Q->length==MAX_SIZE) return true;

	else return false;


}

//4、入队
bool insertQueue(Queue *&Q,dateType date,int prority){
    
    
	
	//基本判断,然后在插入
	
	if(!Q) return false;

	if(isFully(Q)) printf("队列已满无法插入!\n");

	Node *node = new Node;	
	node->data =date;
	node->prority = prority;
	node->next = NULL;

	if(isEmpty(Q)) {
    
    
		//空队列时
		Q->front=Q->rear=node;

	}else{
    
    
		//插到尾部
		Q->rear->next = node;
		Q->rear = node;
	}

	Q->length++;

	printf("成功插入元素:%d prority:%d",node->data,node->prority);

	return true;

}

//5、出队
bool deleteQueue(Queue *Q){
    
    
	//判断优先级再出去
	
	if(!Q) return false;

	if(isEmpty(Q)) {
    
    
		printf("队列为空!");
		return false;
	}
	
	Node **prev = NULL;
	Node *tmp = NULL;
	Node *last = NULL;
	Node *prev_last=NULL;	//记录的是被删掉结点的前一个结点

	//找到优先级判断
	
	prev = &(Q->front);  
	Node *fllow;
	tmp = Q->front;
	last = Q->front;

	while(tmp->next){
    
    

		last = tmp;
		tmp = tmp->next;
		fllow = tmp;
		if(tmp->prority>(*prev)->prority) {
    
    
			
			printf("抓取到一个更大的优先级:data%d prority:%d",tmp->data,tmp->prority);
			//这里只能通过二级指针的方式来进行
			//prev = &fllow;    这样不行
			//prev = &tmp;     这样也不行,因为这样的化*prev->protity的值时时刻刻跟着tmp变化,别忘了这里可是二级指针
	
			prev = &(last->next);
		
			//这里面我让这个prev指向fllow都不不行,delete掉的只是一块内存,那么指针并没有被
			
			prev_last = last;	//记录的是被干掉结点的前一个结点的指针
		}

	}

		tmp = *prev;
		*prev = (*prev)->next;
	
		delete tmp;
		Q->length--;

	//如果只有一个结点被干掉了
		if(Q->length==0){
    
    
			Q->rear = NULL;
		
		}

	//如果prority恰好是尾的结点那么,把rear指向被干掉结点的前面一个结点
	if(prev_last&&prev_last->next==NULL)  {
    
    //有疑问,为什么要判断prev_last结点是否存在,如果它不存在代表就只有一个结点啊?不是上面一步判断了的吗?哦我知道了,只有一格节点他也会下来的因为并没有返回
		Q->rear = prev_last;		

	}

	return true;

}


//6、遍历
void initPrint(Queue *Q){
    
    
	if(!Q) return;

	if(isEmpty(Q)){
    
    
	printf("队列为空!\n");
	return ;
	}

	Node *tmp = Q->front;

	while(tmp){
    
    
	
		printf("date:%d prority:%d\t",tmp->data,tmp->prority);
		
		tmp = tmp->next;
	}


}

//7、获取元素个数							
int getLength(Queue *Q){
    
    
	
	return Q->length;
}

//8、清空队列
void ClearQueue(Queue *Q){
    
    
	
	Node *p = Q->front;
	Node *tmp =NULL;

	while(p){
    
    
		
		tmp = p;
		p=p->next;
		delete tmp;

	}

	Q->front=Q->front = 0;
	Q->length = 0;

}

int main(void){
    
    

	Queue *Q = new Queue;

	if(initQueue(Q)){
    
    
	printf("初始化队列成功!\n");
	}else{
    
    
	printf("初始化队列失败!\n");
	}
	//入队

	Node *node = NULL;
	int date = -1;
	int priority = 1;

	for(int i=0;i<5;i++){
    
    
		date = i;
		priority = i*i;
		
		insertQueue(Q,date,priority);
	}
	printf("\n");

	initPrint(Q);
	
	int length = getLength(Q);
	printf("Length:%d\n",length);

	//出队
	for(int i=0;i<5;i++){
    
    
	deleteQueue(Q);
	printf("\n");
	printf("出列之后:\n");
	

	initPrint(Q);
	}

	system("pause");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_45825875/article/details/115287079