0. 簡介
普通的隊列是一種先進先出的數據結構,元素在隊列尾追加,而從隊列頭刪除。在優先隊列中,元素被賦予優先級。當訪問元素時,具有最高優先級的元素最先刪除。優先隊列具有最高級先出(first in, largest out)的行爲特徵。通常採用堆數據結構來實現。
1. 代碼實現
本代碼採用C#編寫,包含優先隊列的幾種常用操作:
- 入隊
- 隊首元素
- 出隊
- 隊列中元素數量
此外,還有一個相應的測試程序,測試算法是否正確。
using System;
using System.Collections.Generic;
namespace DataStructure {
public class PriorityQueue {
// 數組形式的堆
int[] heap = new int[100000];
// 隊列中元素的數量
public int Count { get; private set; } = 0;
// 入隊
// 將新的元素從樹葉 上移 到合適的位置
public void Push(int val) {
heap[++Count] = val;
int cur = Count;
int parent;
while ((parent = Parent(cur)) >= 1 && heap[cur] > heap[parent]) {
Swap(ref heap[cur], ref heap[parent]);
cur = parent;
}
}
// 返回隊首元素
// 隊首元素位於堆頂,一定是最大的元素
public int Top() {
return heap[1];
}
// 出隊
// 彈出堆頂元素,將堆中最後一個元素置於堆頂,然後 下移 到合適的位置
public int Pop() {
int top = heap[1];
heap[1] = heap[Count--];
int cur = 1;
while (true) {
int leftChild = LeftChild(cur);
int rightChild = RightChild(cur);
if (leftChild <= Count && heap[cur] < heap[leftChild] && (rightChild > Count || heap[leftChild] >= heap[rightChild])) {
Swap(ref heap[cur], ref heap[leftChild]);
cur = leftChild;
} else if (rightChild <= Count && heap[cur] < heap[rightChild]) {
Swap(ref heap[cur], ref heap[rightChild]);
cur = rightChild;
} else {
break;
}
}
return top;
}
// 左孩子結點
static int LeftChild(int node) {
return node << 1;
}
// 右孩子結點
static int RightChild(int node) {
return (node << 1) | 1;
}
// 雙親結點
static int Parent(int node) {
return node >> 1;
}
// 交換兩個變量
static void Swap<T>(ref T a, ref T b) {
T temp = a;
a = b;
b = temp;
}
}
// 測試類,用於測試算法的正確性
class Test {
static void Main(string[] args) {
PriorityQueue pq = new PriorityQueue();
Random random = new Random();
List<int> list = new List<int>();
while (list.Count <= 10000) {
Console.WriteLine("Count: {0}", list.Count);
int choice = random.Next(0, 4);
if (choice == 0) {
if (list.Count > 0) {
int top1 = list[list.Count - 1];
list.RemoveAt(list.Count - 1);
int top2 = pq.Pop();
if (top1 != top2 || list.Count != pq.Count) {
throw new Exception("Wrong in Pop()!");
}
}
} else if (choice == 1) {
if (list.Count > 0) {
int top1 = list[list.Count - 1];
int top2 = pq.Top();
if (top1 != top2) {
throw new Exception("Wrong in Top()!");
}
}
} else {
int val = random.Next(0, 1000);
list.Add(val);
list.Sort();
pq.Push(val);
if (list.Count != pq.Count) {
throw new Exception("Wrong in Push()!");
}
}
}
while (list.Count > 0) {
Console.WriteLine("Count: {0}", list.Count);
int top1 = list[list.Count - 1];
list.RemoveAt(list.Count - 1);
int top2 = pq.Pop();
if (top1 != top2 || list.Count != pq.Count) {
throw new Exception("Wrong in Pop()!");
}
}
Console.WriteLine("恭喜,您的代碼通過了測試!");
}
}
}