【问题标题】:Heap class in .NET [duplicate].NET 中的堆类 [重复]
【发布时间】:2011-01-14 23:09:27
【问题描述】:

可能重复:
Fibonacci, Binary, or Binomial heap in c#?

.NET 中有没有像堆这样的类? 我需要某种可以从中检索 min 的集合。元素。我只想要 3 种方法:

  • Add()
  • RemoveMinElement()
  • GetMinElement()

我不能使用排序列表,因为键必须是唯一的,而且我可能有几个相同的元素。

【问题讨论】:

标签: c# .net heap


【解决方案1】:

您可以将SortedListSortedDictionary(见下文讨论)与自定义键一起使用。如果您使用具有引用相等性的类型,但可以根据您关心的值进行比较,那么这可以工作。

类似这样的:

class HeapKey : IComparable<HeapKey>
{
    public HeapKey(Guid id, Int32 value)
    {
        Id = id;
        Value = value;
    }

    public Guid Id { get; private set; }
    public Int32 Value { get; private set; }

    public int CompareTo(HeapKey other)
    {
        if (_enableCompareCount)
        {
            ++_compareCount;
        }

        if (other == null)
        {
            throw new ArgumentNullException("other");
        }

        var result = Value.CompareTo(other.Value);

        return result == 0 ? Id.CompareTo(other.Id) : result;
    }
}

这是一个使用具有二进制堆性能特征的SortedDictionary 的工作示例:

using System;
using System.Collections.Generic;
using System.Linq;

namespace SortedDictionaryAsBinaryHeap
{
    class Program
    {
        private static Boolean _enableCompareCount = false;
        private static Int32 _compareCount = 0;

        static void Main(string[] args)
        {
            var rnd = new Random();

            for (int elementCount = 2; elementCount <= 6; elementCount++)
            {
                var keyValues = Enumerable.Range(0, (Int32)Math.Pow(10, elementCount))
                    .Select(i => new HeapKey(Guid.NewGuid(), rnd.Next(0, 10)))
                    .ToDictionary(k => k);
                var heap = new SortedDictionary<HeapKey, HeapKey>(keyValues);

                _compareCount = 0;
                _enableCompareCount = true;
                var min = heap.First().Key;
                _enableCompareCount = false;
                Console.WriteLine("Element count: {0}; Compare count for getMinElement: {1}",
                                  (Int32)Math.Pow(10, elementCount),
                                  _compareCount);   
                
                _compareCount = 0;
                _enableCompareCount = true;
                heap.Remove(min);
                _enableCompareCount = false;
                Console.WriteLine("Element count: {0}; Compare count for deleteMinElement: {1}", 
                                  (Int32)Math.Pow(10, elementCount),  
                                  _compareCount);   
            }

            Console.ReadKey();
        }

        private class HeapKey : IComparable<HeapKey>
        {
            public HeapKey(Guid id, Int32 value)
            {
                Id = id;
                Value = value;
            }

            public Guid Id { get; private set; }
            public Int32 Value { get; private set; }

            public int CompareTo(HeapKey other)
            {
                if (_enableCompareCount)
                {
                    ++_compareCount;
                }

                if (other == null)
                {
                    throw new ArgumentNullException("other");
                }

                var result = Value.CompareTo(other.Value);

                return result == 0 ? Id.CompareTo(other.Id) : result;
            }
        }
    }
}

结果:

元素数:100;比较 getMinElement 的计数:0

元素数:100;比较 deleteMinElement 的计数:8

元素数:1000;比较 getMinElement 的计数:0

元素数:1000;比较 deleteMinElement 的计数:10

元素数:10000;比较 getMinElement 的计数:0

元素数:10000;比较 deleteMinElement 的计数:13

元素数:100000;比较 getMinElement 的计数:0

元素数:100000;比较 deleteMinElement 的计数:14

元素数:1000000;比较 getMinElement 的计数:0

元素数:1000000;比较 deleteMinElement 的计数:21

【讨论】:

  • SortedList 太过分了,性能会更差。
  • @codek,SortedList 将有 O(n) 或 O(nlog(n)) 性能,PQ 将在 O(log(n)) 中添加/删除
  • 没有堆是一种实现!=二叉(搜索)树。见en.wikipedia.org/wiki/Priority_queue#Simple_implementations
  • codekaizen,并不是所有的二叉树都是一样的。 SortedList 有 O(n) 的插入和删除 (msdn.microsoft.com/en-us/library/ms132319%28VS.85%29.aspx)。对于 insert 或 deleteMin/Max,二叉堆的最坏情况为 O(log n)。
  • 我并不是说二进制堆对所有应用程序都更好。我的意思是,当您想要堆性能特征时(就像 OP 一样), SortedList 是错误的。我相信 SortedDictionary 在这里也是错误的。它是 /not/ 使用二进制堆实现的,也没有声称是。相反,它使用二叉搜索树。本质区别之一是 SortedDictionary 不能在恒定时间内执行 getMinElement。
【解决方案2】:

优先队列看起来很适合您的问题: Priority queue in .Net

Google 搜索“C# 优先级队列”以获得更多实现。

【讨论】:

猜你喜欢
  • 2012-05-01
  • 2011-04-13
  • 2011-09-25
  • 2016-06-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-07
  • 2010-12-06
相关资源
最近更新 更多