数据结构与算法——优先队列
英雄联盟游戏里面防御塔都有一个自动攻击功能,小兵排着队进入防御塔的攻击范围,防御塔先攻击靠得最近的小兵,这时候大炮车的优先级更高(因为系统判定大炮车对于防御塔的威胁更大),所以防御塔会优先攻击大炮车。而当大炮车阵亡,剩下的全部都是普通小兵,这时候离得近的优先级越高,防御塔优先攻击距离更近的小兵。
优先队列:它的入队顺序没有变化,但是出队的顺序是根据优先级的高低来决定的。优先级高的优先出队。
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 }
===================================================================================================================