二进制搜索SortedList的键

我需要为线性插值编写一些代码,并且我试图找出最有效的方法来搜索SortedList的键,用于围绕我的目标键的上下键。

 SortedList xyTable = new SortedList() { {1, 10}, {2, 20}, {3, 30}, {4,40} }; double targetX = 3.5; 

搜索列表并确定3.5介于3和4之间的最有效方法是什么? 我有一个适用于整数的方法/作弊(暂时将目标键插入列表然后找到索引)但我想我会问专业人员所以我可以生成高质量的代码。

谢谢。

二进制搜索在列表中为您提供了不错的性能。 但是, SortedList上的Keys属性是IList类型,而BinarySearch是在List上定义的。 幸运的是,您可以在此相关问题中找到IList二进制搜索的实现:

如何在IList 上执行二进制搜索?

在我的情况下,源SortedList没有太大变化,因为它被用作查找表。 因此,在这种情况下,将SortedListList一次是有意义的。 之后,使用List的内置BinarySearch方法非常容易……

 double targetX = 3.5; // Assume keys are doubles, may need to convert to doubles if required here. // The below line should only be performed sparingly as it is an O(n) operation. // In my case I only do this once, as the list is unchanging. List keys = xyTable.Keys.ToList(); int ipos = keys.BinarySearch(targetX); if (ipos >= 0) { // exact target found at position "ipos" } else { // Exact key not found: BinarySearch returns negative when the // exact target is not found, which is the bitwise complement // of the next index in the list larger than the target. ipos = ~ipos; if (ipos >= 0 && ipos < keys.Count) { if (ipos > 0) { // target is between positions "ipos-1" and "ipos" } else { // target is below position "ipos" } } else { // target is above position "ipos" } } 

来自MSDN,

SortedList对象的元素按键按照创建SortedList时指定的特定IComparer实现进行排序,或者根据键本身提供的IComparable实现进行排序。 索引序列基于排序顺序。 添加元素时,会以正确的排序顺序将其插入到SortedList中,并且索引会相应地进行调整。 删除元素后,索引也会相应调整。 因此,特定键/值对的索引可能会随着在SortedList中添加或删除元素而更改。

*****此方法使用二进制搜索算法; 因此,此方法是O(log n)操作,其中n是Count。*****

从.NET Framework 2.0开始,此方法使用集合的对象的项目上的Equals和CompareTo方法来确定项是否存在。 在早期版本的.NET Framework中,通过对集合中的对象使用item参数的Equals和CompareTo方法进行此确定。

换句话说,SortedList中的方法IndexOfKey实际上已经使用了binarySearch算法,因此在您的情况下不需要将SortedList转换为List。

希望能帮助到你..

 public class Bounds { int lower; int upper; public Bounds(int lower, int upper) { this.lower = lower; this.upper = upper; } } public Bounds BinarySearch(List keys, double target) { // lower boundary case returns the smallest key as the lower and upper bounds if (target < keys[0]) return new Bounds(0, 0); else if (target < keys[1]) return new Bounds(0, 1); // upper boundary case returns the largest key as the lower and upper bounds else if (target > keys[keys.Length - 1]) return new Bounds(keys.Length - 1, keys.Length - 1); else if (target > keys[keys.Length - 2]) return new Bounds(keys.Length - 2, keys.Length - 1); else return BinarySearch(keys, target, 0, keys.Length - 1); } // 'keys' is a List storing all of the keys from your SortedList. public Bounds BinarySearch(List keys, double target, int lower, int upper) { int middle = (upper + lower)/2; // target is equal to one of the keys if (keys[middle] == target) return new Bounds(middle - 1, middle + 1); else if (keys[middle] < target && keys[middle + 1] > target) return new Bounds(middle, middle + 1); else if (keys[middle] > target && keys[middle - 1] < target) return new Bounds(middle - 1, middle); if (list[middle] < target) return BinarySearch(list, target, lower, upper/2 - 1); if (list[middle] > target) return BinarySearch(list, target, upper/2 + 1, upper); } 

这可能有用..我没有测试出来。 如果没有,希望它足够接近你可以用它进行微调。 这是一个奇怪的问题,因此我处理了所有边界情况,因此当范围降至2个元素或更少时,我不必考虑算法会做什么。