简述用C#实现优先队列方法

开发 后端
在微软的.NET Framework的类中,并没有如同Java等其他语言所有的PriorityQueue类,也就是优先队列类。那么作者通过C#实现了这一方法,在这里与大家共同探讨。

优先队列(priority queue) 是很重要的数据结构。我在做 ACM 题时就经常要用到她。C++ STL 就包括 priority_queue 。Java 也有 PriorityQueue 类。遗憾的是,.NET Framework Base Class Library 中并不包括优先队列。于是,我只好自己用 C# 语言写一个,如下所示:

using System;
using System.Collections.Generic;

namespace Skyiv.Util
{
class PriorityQueue
  {
    IComparer comparer;
    T[] heap;

public int Count { get; private set; }

    public PriorityQueue() : this(null) { }
    public PriorityQueue(int capacity) : this(capacity, null) { }
    public PriorityQueue(IComparer comparer) : this(16, comparer) { }

    public PriorityQueue(int capacity, IComparer comparer)
    {
      this.comparer = (comparer == null) ? Comparer.Default : comparer;
      this.heap = new T[capacity];
    }

    public void Push(T v)
    {
      if (Count >= heap.Length) Array.Resize(ref heap, Count * 2);
      heap[Count] = v;
      SiftUp(Count++);
    }

    public T Pop()
    {
      var v = Top();
      heap[0] = heap[--Count];
      if (Count > 0) SiftDown(0);
      return v;
    }

    public T Top()
    {
      if (Count > 0) return heap[0];
      throw new InvalidOperationException("优先队列为空");
    }

    void SiftUp(int n)
    {
      var v = heap[n];
      for (var n2 = n / 2; n > 0 && comparer.Compare(v, heap[n2]) > 0; n = n2, n2 /= 2)

heap[n] = heap[n2];
      heap[n] = v;
    }

    void SiftDown(int n)
    {
      var v = heap[n];
      for (var n2 = n * 2; n2 < Count; n = n2, n2 *= 2)
      {
        if (n2 + 1 < Count && comparer.Compare(heap[n2 + 1], heap[n2]) > 0) n2++;
        if (comparer.Compare(v, heap[n2]) >= 0) break;
        heap[n] = heap[n2];
      }
      heap[n] = v;
    }
  }
}

如上所示,这个 PriorityQueue 泛型类提供四个公共构造函数,第一个是无参的构造函数,其余的构造函数允许指定优先队列中包括的初始元素数(capacity)、如何对键进行比较(comparer)。

这个程序使用堆(heap)来实现优先队列。所以,所需的空间是最小的。Count 属性和 Top 方法的时间复杂度是 O(1),Push 和 Pop 方法的时间复杂度都是 O(logN)。

我曾经用 List 泛型类实现过一个优先队列,请参见我的博客 Timus1016. A Cube on the Walk 。虽然更简单,程序代码只有 23 行,但是效率不高,其 Push 和 Pop 方法的时间复杂度都是 O(N)。

【编辑推荐】

  1. 详解C#编程中的反射机制与方法
  2. C#中使用扩展方法对调用进行验证
  3. 详解C#代码文件生成扩展代码文件
责任编辑:彭凡 来源: cnblogs
相关推荐

2009-08-20 14:22:17

C#实现 Contro

2009-08-19 17:00:07

C#实现PrintPa

2022-08-11 08:03:43

队列

2009-09-09 14:20:18

C# XML解析XML解析方法

2009-08-26 09:26:12

C#语言层次划分

2021-06-10 00:13:43

C#队列数据

2021-03-26 05:54:00

C#数据方法

2009-09-07 09:36:29

C# DisposeDispose方法

2009-09-11 11:39:23

C# RadioBut

2021-03-27 11:02:04

JavaScript队列编程语言

2011-05-23 17:00:29

2009-08-28 17:10:59

C#线程优先级

2011-12-02 10:58:06

数据结构Java

2009-09-02 18:53:28

C#鼠标坐标

2009-08-25 14:26:28

C#播放AVI文件

2009-09-10 17:37:01

C# get post

2009-08-26 18:11:52

前台与后台方法互调

2009-09-10 18:06:25

C# button快捷

2023-12-07 12:59:46

C语言循环队列代码

2009-09-11 09:59:47

点赞
收藏

51CTO技术栈公众号