【问题标题】:Does a sorted queue exist in .NET?.NET 中是否存在排序队列?
【发布时间】:2010-11-29 16:32:31
【问题描述】:

我需要一个相当专业的 .NET 集合,我不认为 BCL 可以帮助我,但我想如果有人知道类似的东西,我会把它扔在那里。

基本上,我的要求是:

  • 我有一个值对列表,例如:(3, 10), (5, 10), (3, 7), (5, 5)
  • 顺序很重要,即。 (3, 10) != (10, 3)
  • 单个值的重复是可以的,但应该删除重复的对(最好是静默)。
  • 关键是,我需要一直对这个列表进行排序。我只对排序算法在任何时候定义的列表中的第一个值感兴趣。

所以,我希望能够做一些示例代码(正如我所设想的那样,它可能会被实现,其他符合上述要求的实现也可以):

public class Pair
{
    public Pair(int first, int second)
    { First = first; Second = second; }
    public int First { get; set; }
    public int Second { get; set; }
}

SortedQueue<Pair> foo = new SortedQueue<Pair>((left, right) => {
    return right.First - left.First;
});

foo.Add(new Pair(10, 3));
foo.Add(new Pair(4, 6));
foo.Add(new Pair(6, 15));
foo.Add(new Pair(6, 13)); // This shouldn't cause a problem

Pair current = foo.Shift(); // current = (4, 6)

【问题讨论】:

    标签: c# collections


    【解决方案1】:

    你看过SortedDictionarySortedList吗?

    【讨论】:

    • 有一瞬间我想我一定是失明了。但是有一个问题,它们都不支持重复键,这是一项要求。
    • 我有消息要告诉你马特:如果你的钥匙重复了,那就是同一个对象。这里的教训是覆盖 Equals 以便它们在您设置的基础上相等。
    • 我上面的例子并不关心键,但是要使用 SortedDictionary 或 SortedList,唯一的方法就是对键进行排序。我想对 values 进行排序。看起来不像可怕的黑客攻击的方法是使用一个值作为键,另一个作为值,而不是使用上面描述的 Pair 类(由于我指出的原因,这不起作用)。另一种方法是使用 Pair 作为键和 null 的所有值...
    • 想想我需要什么作为 SortedQueue 类。这个类比实际上非常有效。
    • @MAtthew Scharley:那么我建议使用我的 LINQ 解决方案。它可以让你根据你想要的任何标准进行排序,你可以围绕它构建一个包装类来简化它的使用。
    【解决方案2】:

    SortedList 是最好的,你所要做的就是在你的 Pair 类中实现 IComparable,它会自动排序它们。至于删除重复项,我认为排序列表无法处理,但您可以继承它并添加此功能。

    【讨论】:

      【解决方案3】:

      您很可能应该使用 The Skeet 在his answer 中提到的 Lookup 类。然后你用这样的方式构建和访问它:

      List<Lookup<int, int>> yourList = new List<Lookup<int, int>>();
      yourList.Add(new Lookup(3,5));
      //...
      var list = from item in yourList
                 orderby list.Key //or whatever sort criteria you want here
                 select item;
      //use list
      

      语法可能在 1 或 2 处有点偏离,但它应该可以工作。

      【讨论】:

        【解决方案4】:

        我引用:

        我需要一直对这个列表进行排序。 我只对第一个感兴趣 列表中的值由 任意时刻的排序算法。

        这听起来你确实想要一个排序队列,而是一个Priority Queue。如果性能是一个问题,那么 PQ 肯定会更快,O(log n) vs O(n)。但是删除重复问题需要您同时保留一个并行的 HashSet。

        【讨论】:

        • 参见“.Net 中的优先队列”,stackoverflow.com/questions/102398/priority-queue-in-net
        • 感谢您提供正确的名称和链接。现在我查看了维基百科的文章,我想实现它的方式是“简单实现”中列出的两种类型的混合(保持一个带有标志的列表是否已排序,只需附加在插入时,然后在检索前根据需要进行排序)。并感谢 dangph 提供一些实际实现的链接。
        • 为了记录,这也是为了实现 A* 搜索,维基百科的文章也有一些注释,所以双重荣誉。
        • 仅供参考,可以在这里找到线程安全的优先级队列实现:code.msdn.microsoft.com/Samples-for-Parallel-b4b76364/…
        【解决方案5】:

        目前 .NET 中没有任何内容可以满足您的所有要求。在 .NET 4.0 中有一个 SortedSet 类。我意识到它现在可能对你没有多大好处。

        如果您实现 IComparable,SortedList 就会接近。您只需使用 Pair 作为键和值。您只会将对您的 Pair 的引用存储两次,因此不会产生巨大的内存开销。但这不会处理重复。

        有很多方法可以自己编写,但没有任何内置方法可以完全满足您的需求。有一些开源的 SortedSet 实现(例如 Spring.Net 中有一个)。这可能是您目前最好的选择。

        【讨论】:

        • 在 Perl/PHP 中多次使用散列来获得对集合类型的访问权之后,每次我只在集合中使用键时,感觉就像是 hack,我想扔掉。不幸的是,这就是我们所坚持的。但!这是一个个人项目,我已经安装了 VS 2010,所以我可能只是使用它...
        【解决方案6】:

        查看C5 Generic Collections Library,它已经有一个您正在寻找的实现,称为IntervalHeap 或优先队列。以下是 C5 Book 中关于它的一些文档:IPriorityQueue&lt;T&gt;

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-08-08
          • 1970-01-01
          • 1970-01-01
          • 2019-12-28
          • 1970-01-01
          • 2018-12-05
          • 1970-01-01
          • 2013-08-29
          相关资源
          最近更新 更多