数据结构 - 优先队列

本文介绍优先队列的概念及其实现方式,重点讲解如何使用堆数据结构来实现优先队列,包括入队、出队、获取队首元素等基本操作,并提供C#代码示例。

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("恭喜,您的代码通过了测试!");
        }
    }
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值