Fork me on GitHub

数据结构与算法——优先队列

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

 

优先队列:它的入队顺序没有变化,但是出队的顺序是根据优先级的高低来决定的。优先级高的优先出队。

 

1 typedef QNode* QueuePtr;
2 typedef struct Queue
3 {
4     int    length;            //队列的长度
5     QueuePtr front;        //队头指针
6     QueuePtr rear;        //队尾指针
7 }LinkQueue;

 

 空的任务队列 & 插入元素

 

优先队列出队

 

  

源码实现:

  1 #include <stdio.h>
  2 #include <assert.h>
  3 #include <Windows.h>
  4 #include <iostream>
  5 #include <iomanip>
  6 
  7 using namespace std;
  8 
  9 #define MaxSize 5        //队列的最大容量
 10 typedef int DataType;    //任务队列中元素类型
 11 
 12 //结点结构
 13 typedef struct _QNode
 14 {
 15     int priority;        //每个节点的优先级,0最低优先级,9最高优先级,优先级相同,取第一个节点
 16     DataType data;
 17     struct _QNode* next;
 18 }QNode;
 19 
 20 typedef QNode* QueuePtr;
 21 
 22 //队列
 23 typedef struct Queue
 24 {
 25     int length;         //队列的长度
 26     QueuePtr front;     //队头指针
 27     QueuePtr rear;      //队尾指针
 28 }LinkQueue;
 29 
 30 //队列初始化,将队列初始化为空队列
 31 void InitQueue(LinkQueue* LQ)
 32 {
 33     if (!LQ) return;
 34     LQ->length = 0;
 35     LQ->front = LQ->rear = NULL;   //把对头和队尾指针同时置0
 36 }
 37 
 38 //判断队列为空
 39 int IsEmpty(LinkQueue* LQ)
 40 {
 41     if (!LQ) return 0;
 42     if (LQ->front == NULL)
 43     {
 44         return 1;
 45     } return 0;
 46 }
 47 
 48 //判断队列是否为满
 49 int IsFull(LinkQueue* LQ)
 50 {
 51     if (!LQ) return 0;
 52     if (LQ->length == MaxSize)
 53     {
 54         return 1;
 55     } return 0;
 56 }
 57 
 58 //入队,将元素data插入到队列LQ中
 59 int EnterQueue(LinkQueue* LQ, DataType data, int priority)
 60 {
 61     if (!LQ) return 0;
 62     if (IsFull(LQ))
 63     {
 64         cout << "无法插入元素 " << data << ", 队列已满!" << endl; return 0;
 65     }
 66     QNode* qNode = new QNode;
 67     qNode->data = data;
 68     qNode->priority = priority;
 69     qNode->next = NULL;
 70     if (IsEmpty(LQ))        //空队列
 71     {
 72         LQ->front = LQ->rear = qNode;
 73     }
 74     else
 75     {
 76         LQ->rear->next = qNode;         //在队尾插入节点qNode
 77         LQ->rear = qNode;               //队尾指向新插入的节点
 78     }
 79     LQ->length++;
 80     return 1;
 81 }
 82 
 83 //出队,遍历队列,找到队列中优先级最高的元素data出队
 84 int DeleteQueue(LinkQueue* LQ, DataType* data)
 85 {
 86     QNode** prev = NULL, * prev_node = NULL;        //保存当前已选举的最高优先级节点上一个节点的指针地址。
 87     QNode*  last = NULL, * tmp = NULL;
 88 
 89     if (!LQ || IsEmpty(LQ))
 90     {
 91         cout << "队列为空!" << endl;
 92         return 0;
 93     }
 94     if (!data) return 0;
 95 
 96     //prev 指向队头 front 指针的地址
 97     prev = &(LQ->front);
 98     printf("第一个节点的优先级: %d\n", (*prev)->priority);
 99 
100     last = LQ->front;       //指向第一个节点
101     tmp = last->next;       //指向第二个节点
102     while (tmp)
103     {
104         if (tmp->priority > (*prev)->priority)
105         {
106             printf("抓到个更大优先级的节点[priority: %d]\n", tmp->priority);
107             prev = &(last->next);       //记录最大的节点
108             prev_node = last;           //指向最大节点的前一个节点,如果删除的是尾部节点,这个变量可以用来判断
109         }
110         //两指针后移
111         last = tmp;             
112         tmp = tmp->next;
113     }
114     *data = (*prev)->data;              //获取最大优先节点的数据
115     tmp = *prev;                        
116     *prev = (*prev)->next;              
117     delete tmp;
118     LQ->length--;
119 
120     //接下来存在2种情况需要分别对待
121     //1.删除的是首节点,而且队列长度为零
122     if (LQ->length == 0)
123     {
124         LQ->rear = NULL;
125     }
126     //2.删除的是尾部节点
127     if (prev_node && prev_node->next == NULL)
128     {
129         LQ->rear = prev_node;
130     }
131     return 1;
132 }
133 
134 //打印队列中的各元素
135 void PrintQueue(LinkQueue* LQ)
136 {
137     QueuePtr tmp;
138     if (!LQ) return;
139     if (LQ->front == NULL)
140     {
141         cout << "队列为空!";
142         return;
143     }
144 
145     tmp = LQ->front; while (tmp)
146     {
147         cout << setw(4) << tmp->data << "[" << tmp->priority << "]";
148         tmp = tmp->next;
149     }
150     cout << endl;
151 }
152 
153 //获取队首元素,不出队
154 int GetHead(LinkQueue* LQ, DataType* data)
155 {
156     if (!LQ || IsEmpty(LQ))
157     {
158         cout << "队列为空!" << endl;
159         return 0;
160     } if (!data) return 0;
161     *data = LQ->front->data;
162     return 1;
163 }
164 
165 //清空队列
166 void ClearQueue(LinkQueue* LQ)
167 {
168     if (!LQ) return;
169     while (LQ->front)
170     {
171         QueuePtr tmp = LQ->front->next;
172         delete LQ->front;
173         LQ->front = tmp;
174     }
175     LQ->front = LQ->rear = NULL;
176     LQ->length = 0;
177 }
178 
179 //获取队列中元素的个数
180 int getLength(LinkQueue* LQ)
181 {
182     if (!LQ) return 0;
183     return LQ->length;
184 }
185 
186 int main()
187 {
188     LinkQueue* LQ = new LinkQueue; DataType data = -1;
189     //初始化队列
190     InitQueue(LQ);
191     //入队
192     for (int i = 0; i < 5; i++)
193     {
194         EnterQueue(LQ, i + 10, i);
195     }
196     //打印队列中的元素
197     printf("队列中的元素(总共%d 个):", getLength(LQ));
198     PrintQueue(LQ);
199     cout << endl;
200 
201     //出队
202     for (int i = 0; i < 5; i++)
203     {
204         if (DeleteQueue(LQ, &data))
205         {
206             cout << "出队的元素是:" << data << endl;
207         }
208         else
209         {
210             cout << "出队失败!" << endl;
211         }
212     }
213     //打印队列中的元素
214     printf("出队五个元素后,队列中剩下的元素[%d]:\n", getLength(LQ));
215     PrintQueue(LQ);
216     cout << endl;
217     ClearQueue(LQ);
218     cout << "清空队列!\n";
219     PrintQueue(LQ);
220 
221     //清理资源
222     delete LQ;
223     system("pause");
224     return 0;
225 }

 

 

 

 

 

 

===================================================================================================================

 

posted @ 2020-09-02 16:45  索智源  阅读(177)  评论(0编辑  收藏  举报