數據結構 - 優先隊列

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("恭喜,您的代碼通過了測試!");
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章