C# 我是否应该使用电源采集';是否将OrderedMultiDictionary作为优先级队列?

C# 我是否应该使用电源采集';是否将OrderedMultiDictionary作为优先级队列?,c#,.net,data-structures,priority-queue,C#,.net,Data Structures,Priority Queue,C#不提供优先级队列的本机实现 对于Stackoverflow,解决此类问题的常见方法是使用 我应该继续这样做,还是有什么缺点?Power Collections确实提供了一些在.NET framework中尚未出现的常用数据结构的优秀实现。虽然采用这种方法并不可怕,但我想指出这种方法的一个重要缺陷 OrderedMultiDictionary(以及所有其他Power Collection类)使用红黑树创建键值对的有序包。对于优先级队列,RB树往往是低级数据结构。我假设优先级值可以散列成整数 原

C#不提供优先级队列的本机实现

对于Stackoverflow,解决此类问题的常见方法是使用


我应该继续这样做,还是有什么缺点?

Power Collections确实提供了一些在.NET framework中尚未出现的常用数据结构的优秀实现。虽然采用这种方法并不可怕,但我想指出这种方法的一个重要缺陷

OrderedMultiDictionary(以及所有其他Power Collection类)使用红黑树创建键值对的有序包。对于优先级队列,RB树往往是低级数据结构。我假设优先级值可以散列成整数

原因很简单-字典可以立即跳转到O(1)中的特定优先级值,其中is可以使用专门的数据结构来存储该优先级的值(即队列)

试验 为了验证我的说法,我编写了一个简单的基准测试,根据3种不同的想法比较优先级队列结构:

  • Power Collections OrderedMultiDictionary
  • 分类词典
  • 字典
  • 第二个选项使用,内部实现为BST。第三个选项使用带有O(1)查找的简单字典

    我使用不同数量的元素(如Y轴所示)和不同数量的不同值(如X轴所示)进行测试。特定组合的结果显示为3x3值矩阵。第一行是选项1(OrderdMultiDictionary,第二行是SortedDictionary,第三行是Dictionary)。这三行中的第一个值显示了将相应数量的值排入队列所需的时间,第二行是枚举所有值所需的时间,第三行是再次将所有值移出队列所需的时间

    所有时间均为log2。值为10表示2^10ms=1s,但绝对值的重要性较低。元素的数量增加了一倍,这意味着,如果结构表现为O(n)型,则时间应每增加一次

    在水平方向上,不同值的数量乘以每列32。因此,第一列(重复插入相同的值)显示了保存这些值的内部数据结构的性能

    所使用的机器是一台配备16 GB plus SSD的i7

              |           1        |          32        |        1024        |       32768        |     1048576        |
    
           128
              | -4.9 / -4.3 /  n/a | -4.7 / -4.1 /  n/a | -4.8 / -2.9 /  n/a | -4.9 / -2.9 /  n/a | -4.9 / -2.9 /  n/a |
              | -7.5 / -6.1 / -5.3 | -6.5 / -5.7 / -5.1 | -4.7 / -4.9 / -4.3 | -4.6 / -4.7 / -4.2 | -4.6 / -4.8 / -4.2 |
              | -7.5 / -7.6 / -6.6 | -6.8 / -7.3 / -6.3 | -5.9 / -5.9 / -3.0 | -6.2 / -6.4 / -2.8 | -6.2 / -6.3 / -2.8 |
    
    
           256
              | -3.8 / -3.2 /  n/a | -3.7 / -3.1 /  n/a | -3.7 / -2.2 /  n/a | -3.8 / -1.8 /  n/a | -3.7 / -1.8 /  n/a |
              | -6.8 / -5.5 / -4.4 | -5.8 / -5.4 / -4.2 | -3.8 / -4.3 / -3.4 | -3.5 / -4.1 / -3.2 | -3.5 / -4.1 / -3.1 |
              | -6.6 / -6.9 / -5.7 | -6.1 / -6.7 / -5.7 | -5.5 / -5.3 / -1.8 | -5.3 / -5.0 / -0.9 | -5.3 / -5.6 / -1.0 |
    
    
           512
              | -2.7 / -2.1 /  n/a | -2.5 / -2.1 /  n/a | -2.5 / -1.5 /  n/a | -2.6 / -0.7 /  n/a | -2.6 / -0.7 /  n/a |
              | -5.9 / -5.2 / -3.4 | -4.9 / -5.0 / -3.3 | -3.2 / -4.2 / -2.6 | -2.4 / -3.2 / -2.1 | -2.3 / -3.2 / -2.0 |
              | -5.7 / -6.1 / -4.9 | -5.2 / -6.1 / -4.8 | -4.8 / -5.0 / -1.7 | -4.3 / -4.0 /  1.0 | -4.4 / -4.7 /  1.0 |
    
    
          1024
              | -1.6 / -1.0 /  n/a | -1.4 / -1.0 /  n/a | -1.4 / -0.7 /  n/a | -1.5 /  0.4 /  n/a | -1.5 /  0.3 /  n/a |
              | -4.9 / -4.7 / -2.4 | -4.1 / -4.5 / -2.3 | -2.6 / -4.0 / -1.8 | -1.2 / -2.3 / -1.0 | -1.2 / -2.3 / -0.9 |
              | -4.7 / -5.4 / -3.9 | -4.4 / -5.3 / -3.8 | -4.1 / -4.6 / -1.6 | -3.3 / -3.0 /  2.9 | -3.5 / -3.8 /  3.0 |
    
    
          2048
              | -0.4 /  0.1 /  n/a | -0.3 /  0.1 /  n/a | -0.3 /  0.3 /  n/a | -0.3 /  1.5 /  n/a | -0.5 /  1.4 /  n/a |
              | -4.0 / -4.1 / -1.4 | -3.2 / -4.0 / -1.3 | -1.7 / -3.5 / -0.9 | -0.2 / -1.4 /  0.1 | -0.2 / -1.3 /  0.1 |
              | -3.8 / -4.5 / -2.9 | -3.5 / -4.4 / -2.9 | -3.2 / -3.9 / -1.0 | -2.5 / -2.0 /  4.9 | -2.4 / -2.1 /  4.9 |
    
    
          4096
              |  0.7 /  1.2 /  n/a |  0.8 /  1.2 /  n/a |  0.9 /  1.3 /  n/a |  0.8 /  2.8 /  n/a |  0.6 /  2.9 /  n/a |
              | -3.0 / -3.2 / -0.4 | -2.2 / -3.3 / -0.3 | -0.8 / -3.0 /  0.1 |  0.9 / -0.4 /  1.1 |  0.9 / -0.2 /  1.2 |
              | -2.9 / -3.5 / -1.9 | -2.6 / -3.5 / -1.9 | -2.3 / -3.2 / -0.9 | -1.6 / -1.1 /  6.6 | -1.3 / -1.1 /  6.9 |
    
    
          8192
              |  1.8 /  2.8 /  n/a |  1.9 /  3.0 /  n/a |  2.0 /  3.0 /  n/a |  1.9 /  4.0 /  n/a |  1.8 /  4.1 /  n/a |
              | -2.0 / -2.4 /  0.6 | -1.3 / -2.4 /  0.7 |  0.1 / -2.2 /  1.1 |  1.8 /  0.4 /  2.1 |  2.1 /  0.9 /  2.3 |
              | -1.9 / -2.6 / -1.0 | -1.6 / -2.5 / -0.9 | -1.4 / -2.4 / -0.3 | -0.6 / -0.3 /  8.0 | -0.5 /  0.1 /  8.9 |
    
    
         16384
              |  2.9 /  3.7 /  n/a |  3.0 /  3.6 /  n/a |  3.1 /  3.8 /  n/a |  3.1 /  4.6 /  n/a |  3.0 /  5.2 /  n/a |
              | -1.0 / -1.5 /  1.6 | -0.3 / -1.5 /  1.7 |  1.1 / -1.4 /  2.0 |  2.4 /  0.7 /  2.9 |  3.2 /  1.9 /  3.6 |
              | -0.9 / -1.6 /  0.0 | -0.6 / -1.6 /  0.1 | -0.5 / -1.5 /  0.4 |  0.0 / -0.1 /  8.0 |  0.6 /  1.2 / 10.9 |
    
    
         32768
              |  4.0 /  5.0 /  n/a |  4.1 /  5.0 /  n/a |  4.3 /  5.0 /  n/a |  4.2 /  5.5 /  n/a |  4.1 /  6.4 /  n/a |
              | -0.1 / -0.5 /  2.6 |  0.7 / -0.5 /  2.7 |  2.0 / -0.5 /  3.1 |  3.1 /  0.9 /  3.8 |  4.3 /  3.0 /  4.8 |
              |  0.1 / -0.6 /  1.0 |  0.4 / -0.6 /  1.1 |  0.5 / -0.5 /  1.3 |  0.9 /  0.4 /  8.0 |  1.6 /  2.3 / 12.9 |
    
    
         65536
              |  5.2 /  6.6 /  n/a |  5.4 /  6.4 /  n/a |  5.5 /  6.4 /  n/a |  5.5 /  6.8 /  n/a |  5.4 /  7.4 /  n/a |
              |  1.0 /  0.4 /  3.6 |  1.8 /  0.5 /  3.7 |  3.0 /  0.4 /  4.1 |  4.2 /  1.9 /  4.9 |  5.5 /  4.2 /  6.0 |
              |  1.1 /  0.4 /  2.0 |  1.4 /  0.4 /  2.1 |  1.5 /  0.5 /  2.4 |  2.0 /  1.4 /  9.8 |  3.2 /  3.4 / 14.8 |
    
    
        131072
              |  6.5 /  7.8 /  n/a |  6.6 /  7.6 /  n/a |  6.8 /  7.4 /  n/a |  6.9 /  7.7 /  n/a |  6.8 /  8.6 /  n/a |
              |  2.0 /  1.4 /  4.6 |  2.9 /  1.4 /  4.8 |  4.1 /  1.5 /  5.2 |  5.2 /  2.4 /  5.8 |  6.8 /  5.4 /  7.0 |
              |  2.1 /  1.4 /  3.1 |  2.4 /  1.4 /  3.1 |  2.5 /  1.5 /  3.3 |  3.0 /  2.0 /  9.9 |  4.4 /  4.6 / 16.6 |
    
    
        262144
              |  7.5 /  8.9 /  n/a |  7.6 /  8.9 /  n/a |  7.8 /  8.6 /  n/a |  8.0 /  8.8 /  n/a |  8.2 /  9.6 /  n/a |
              |  3.0 /  2.4 /  5.6 |  3.9 /  2.4 /  5.7 |  5.1 /  2.4 /  6.1 |  6.1 /  2.9 /  6.7 |  8.1 /  6.4 /  8.1 |
              |  3.1 /  2.5 /  4.1 |  3.3 /  2.4 /  4.1 |  3.5 /  2.4 /  4.2 |  4.7 /  3.6 /  9.9 |  5.7 /  5.8 / 18.2 |
    
    
        524288
              |  8.6 / 10.0 /  n/a |  8.8 / 10.0 /  n/a |  9.0 /  9.6 /  n/a |  9.4 /  9.7 /  n/a |  9.3 / 10.4 /  n/a |
              |  4.0 /  3.4 /  6.6 |  4.9 /  3.4 /  6.7 |  6.1 /  3.4 /  7.1 |  7.0 /  3.7 /  7.6 |  8.9 /  7.0 /  8.8 |
              |  4.1 /  3.5 /  5.0 |  4.4 /  3.4 /  5.1 |  4.5 /  3.4 /  5.2 |  4.9 /  3.6 /  9.9 |  6.8 /  6.5 / 19.2 |
    
    
       1048576
              |  9.7 / 11.0 /  n/a |  9.9 / 11.1 /  n/a | 10.2 / 10.7 /  n/a | 10.7 / 10.7 /  n/a | 10.7 / 11.2 /  n/a |
              |  5.0 /  4.4 /  7.5 |  5.9 /  4.4 /  7.7 |  7.1 /  4.4 /  8.1 |  8.0 /  4.6 /  8.5 |  9.7 /  7.3 /  9.8 |
              |  5.1 /  4.4 /  n/a |  5.3 /  4.4 /  n/a |  5.5 /  4.4 /  n/a |  5.9 /  4.6 /  n/a |  7.7 /  6.8 /  n/a |
    
    
       2097152
              | 10.8 / 12.0 /  n/a | 11.0 / 12.1 /  n/a | 11.3 / 11.8 /  n/a | 12.1 / 11.8 /  n/a | 12.0 / 12.1 /  n/a |
              |  6.0 /  5.4 /  8.5 |  7.0 /  5.4 /  8.7 |  8.1 /  5.4 /  9.1 |  9.0 /  5.6 /  9.5 | 10.6 /  7.6 / 10.3 |
              |  6.1 /  5.4 /  n/a |  6.4 /  5.4 /  n/a |  6.6 /  5.4 /  n/a |  6.9 /  5.6 /  n/a |  8.8 /  7.2 /  n/a |
    
    
       4194304
              | 11.9 / 13.0 /  n/a | 12.0 / 13.1 /  n/a | 12.5 / 12.9 /  n/a | 13.3 / 12.8 /  n/a | 13.2 / 13.0 /  n/a |
              |  7.0 /  6.4 /  9.5 |  8.0 /  6.4 /  9.7 |  9.2 /  6.4 / 10.1 | 10.1 /  6.5 / 10.5 | 11.6 /  8.0 / 11.1 |
              |  7.1 /  6.4 /  n/a |  7.3 /  6.4 /  n/a |  7.6 /  6.4 /  n/a |  8.0 /  6.5 /  n/a |  9.9 /  7.7 /  n/a |
    
    
       8388608
              |  n/a /  n/a /  n/a |  n/a /  n/a /  n/a | 13.7 / 14.1 /  n/a | 14.5 / 13.8 /  n/a | 14.4 / 13.9 /  n/a |
              |  8.0 /  7.4 / 10.5 |  9.0 /  7.4 / 10.7 | 10.2 /  7.4 / 11.1 | 11.1 /  7.5 / 11.5 | 12.6 /  8.5 / 12.0 |
              |  8.1 /  7.4 /  n/a |  8.4 /  7.4 /  n/a |  8.6 /  7.4 /  n/a |  9.1 /  7.5 /  n/a | 10.8 /  8.3 /  n/a |
    
    
     16777216
             |  n/a /  n/a /  n/a |  n/a /  n/a /  n/a |  n/a /  n/a /  n/a |  n/a /  n/a /  n/a |  n/a /  n/a /  n/a |
             |  9.0 /  8.4 / 11.6 | 10.0 /  8.4 / 11.7 | 11.2 /  8.4 / 12.1 | 12.2 /  8.4 / 12.5 | 13.6 /  9.1 / 12.9 |
             |  9.1 /  8.4 /  n/a |  9.3 /  8.4 /  n/a |  9.6 /  8.4 /  n/a | 10.1 /  8.4 /  n/a | 11.9 /  9.0 /  n/a |
    
    测试的缺陷 所有值小于100的行都未显示,因为它们没有实际意义,可以被视为正在预热

    所有测试只执行了一次,没有进行平滑处理,因此在任何方向都可能出现峰值。超过10000的测试运行了相当长的时间,以至少排除短峰值。我重复了整个基准测试几次,差异在10%以内

    数据结构尚未使用它们可能希望保存的适当数量的元素进行初始化。这部分是由于较大集合的内存消耗

    OMD退出队列没有任何价值,因为我还没有找到合理的方法来实现这一点。我希望在这方面能得到任何帮助

    结果 对于较大的值,结果相当一致

  • 对于较小的存储桶计数(不同值的数量),基于选项2或3的方法在排队时都比OMD快几倍,在枚举时甚至更快。不存在排队时的比较
  • 对于较大的存储桶计数,OMD不会减速,而选项2+3会减速(系数10)。最终,选项2在排队时稍差,但在枚举时仍然非常快,选项3(简单字典)两者都优于
  • 然而,选项3在对大的存储桶编号进行排队时会变得非常糟糕,以至于无法使用。这是由于对SortedDictionary中不存在的最小密钥的永久搜索
  • 关于内存使用,OMD使用的内存是选项2和选项3的几倍,并且始终抛出超过500万个值的OfMemory异常。选项3再次使用的内存明显少于选项2。每次测试后,都会强制执行完整的垃圾收集

    总之,我建议使用队列排序字典,因为它往往与Power Collection中使用的RB-tree方法一样快,同时使用更少的内存。如果没有明显的优先级值,优势就会增加。当然,这只有在处理大量数据时才重要

    源代码 正在添加SortedDictionary的源代码。有关更多信息,请访问

    公共类优先队列
    {
    私有只读SortedDictionary _D=新SortedDictionary();
    公共无效排队(TK键、TV值)
    {
    队列列表;
    如果(!\u D.TryGetValue(输入,输出列表)){
    list=新队列();
    _D.添加(键、列表);
    }
    列表。排队(值);
    计数++;
    }
    公共整数计数
    {
    得到;
    私人设置;
    }
    公共电视排队()
    {
    var first=_D.first();
    var item=first.Value.Dequeue();
    如果(!first.Value.Any()){
    _D.移除(第一个键);
    }
    退货项目;
    }
    公共IEnumerable值
    {
    得到
    {
    var keys=\u D.keys.ToArray();
    foreach(var键入键){
    foreach(变量项在[key]中){
    收益回报项目;
    }
    }
    }
    }
    }
    
    你怎么能打得这么快?:)
    public class PriorityQueue<TK, TV>
    {
        private readonly SortedDictionary<TK, Queue<TV>> _D = new SortedDictionary<TK, Queue<TV>> ();
    
        public void Enqueue (TK key, TV value)
        {
            Queue<TV> list;
            if (!_D.TryGetValue (key, out list)) {
                list = new Queue<TV> ();
                _D.Add (key, list);
            }
            list.Enqueue (value);
            Count++;
        }
    
        public int Count
        {
            get;
            private set;
        }
    
        public TV Dequeue ()
        {
            var first = _D.First ();
            var item = first.Value.Dequeue ();
            if (!first.Value.Any ()) {
                _D.Remove (first.Key);
            }
            return item;
        }
    
        public IEnumerable<TV> Values
        {
            get
            {
                var keys = _D.Keys.ToArray ();
                foreach (var key in keys) {
                    foreach (var item in _D[key]) {
                        yield return item;
                    }
                }
            }
        }
    }