好吧,說我有一個類型爲int的強類型SortedSet。我想找到集合中小於x的最大數字。如何高效地搜索具有不等式的排序集?
也許這是錯誤的數據結構,但我直覺的想法是,我有一個排序的集合。毫無疑問,我應該能夠通過.NET框架進行這種搜索。
好吧,說我有一個類型爲int的強類型SortedSet。我想找到集合中小於x的最大數字。如何高效地搜索具有不等式的排序集?
也許這是錯誤的數據結構,但我直覺的想法是,我有一個排序的集合。毫無疑問,我應該能夠通過.NET框架進行這種搜索。
由於SortedSet
不提供通過索引直接訪問你必須依靠枚舉(線性搜索 - 爲O(n))。一種可能更好的方法是使用SortedSet.GetViewBetween和Last
,但它看起來不像你可以得到的最後一個元素,但無論如何都沒有枚舉所有元素。
收集與指數直接訪問(即List
)將讓你做O(LG n)的二進制搜索性能 - 因此使用List.BinarySearch時,如果你需要大量的複製搜索到列表可以與ToList
提供更好的整體性能(這給你你正在尋找的下一個元素的位置)。
// starting sample for BinarySearch approach
// not handling case where item not in the list (x = 1).
// List have to be sorted which is the case starting from sorted set: sortedSet.ToList()
var list = new List<int>{ 1,3, 5, 7, 8,9};
var index = list.BinarySearch(8);
Console.WriteLine(index < 0 ? list[~index - 1] : list[index-1]);
除非我失去了一些東西,使用Linq的LastOrDefault
擴展方法:
var lastBefore = set.LastOrDefault(num => num < x); // x is your search number
if (lastBefore < set.ElementAt(0))
{
// Nothing in the set is smaller
}
else
{
// lastBefore is the last number smaller then search number
}
請注意,即使集合被排序並且通常會期望O(lg n)性能,但這是O(n),但就我所知,這是使用'SortedSet'的最佳結果。 –
值得一提的是,必須在執行BinarySearch之前對列表進行排序 - 從msdn頁面的備註部分:「列表必須已根據比較器實現進行排序;否則結果不正確。」 –
@zohar OP從SortedSet開始,所以ToList將會產生排序列表。事實上,如果從其他一些數據開始,那麼排序是第一步 - 但這比原始的線性搜索更糟糕。 –
我完全同意你的看法,這就是爲什麼我提高了你的答案,但這也是我認爲值得一提的原因 - 你的例子沒有在有序集合上使用'.ToList()'... –