【发布时间】:2013-05-13 21:21:59
【问题描述】:
我需要存储一个节点集合:
class Node
{
int Value;
//other info
}
我有三个要求:
- 需要能够有效地检索集合中具有最低值的节点
- 需要能够有效地将节点插入到集合中
- 两个节点可以有相同的值
我认为用于此的最佳集合是某种排序列表。这样,只需从排序列表中获取第一个元素,就可以有效地满足要求 #1。通过在列表中的正确位置插入一个新节点,可以有效地满足要求 #2。
但是 .Net 中的 SortedList 集合类似于 SortedDictionary 并且要求被排序的键是唯一的,这违反了要求 #3。
.Net 中似乎没有满足这些要求的集合,主要是因为确实存在的自排序集合要求排序的键是唯一的。这是什么原因?我认为这不可能是疏忽。我在这里没有抓住什么?我可以找到关于此的类似问题,但它们通常涉及有人建议 SortList,然后意识到这不起作用,然后对话在没有标准解决方案的情况下淡出。至少如果有人会说“C# 中没有用于此任务的集合,您需要一起破解一些东西”,这将是一个答案。
是否可以使用常规的List<Node> 并在添加新节点时重新排序列表?似乎这不如将节点插入到正确的位置开始那样有效。也许这就是我应该做的?手动遍历列表,直到我自己找到插入新节点的位置?
【问题讨论】:
-
你看过C5 Collections吗?那里可能有东西。
-
如果你最终使用了一个你自己排序的
List<Node>,请务必使用List<>的BinarySearch方法找到需要插入新项目的索引。如果这意味着不使用BinarySearch,请不要“手动迭代”。 -
从需求看来你需要一个堆,而不是一个排序列表。将一个项目添加到堆中只需 O(log n),而不是排序列表的 O(n),甚至添加然后重新排序的 O(n log n)。
-
@harold 但是如果他以一个空的
List<Node>开头,并且他总是通过以下方法添加到列表中:public void Add(Node n) { var idx = innerList.BinarySearch(n); if (idx >= 0) { innerList.Insert(idx, n); else { innerList.Insert(~idx, n); } },那么List<Node>总是会自动排序,并且他永远不必致电Sort。当然,Node应该是IComparable<Node>,或者BinarySearch方法应该被赋予一个IComparer<Node>作为它的第二个参数(可以使用.NET 4.5 的Comparer<Node>.Create静态方法创建)。 -
@JeppeStigNielsen 是的,这还不错,属于我提到的 O(n) 情况,因为插入可能会移动很多东西。堆没有这个问题。
标签: c#