故事的引入
话不多说先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;
}