问题
已有一个自定义类型可以像List<T>中的元素那样排序,还要使用BinarySearch方法在该列表对其自定义的类型制定查询规则。
解决方案
使用IComparable<T> 和IComparer<T>接口。使用3-1节中的Square类,以List<T>和SortedList<K,V>集合对Square对象实现排序和查询的方法实现IComparable<T>接口。
讨论
依靠在用户自定义的类(或结构)中实现IComparable<T>接口,可以得到List<T>和SortedList<K,V>类中一样的搜索算法的优势。在这些类中的内置搜索算法中,用户只需要实现IComparable<T>接口告诉这些类要怎样查找用户自定义类型。
关于实现CompareTo方法,可参见3-2节。
List<T>类提供了BinarySearch(二分搜索)方法来对列表中的元素进行搜索。每一个元素都会和另一个作为参数传入BinarySearch方法中的元素对象进行比较。SortedList类型没有包含BinarySearch方法,而是用ContainsKey方法进行代替,该方法对列表中包含的键值进行二分搜索。SortedList类中ContainsValue方法则是使用线性搜索法搜索列表中的值。该方法则是调用SortedList集合中的Equals方法来完成搜索。SortedList类中的线性搜索算法在使用Compare和CompareTo方法时没有任何的优越效果,但是它们在二分搜索上使用很有效。
要使List<T>类型使用BinarySearch方法得到准确的搜索结果,要先调用List<T>方法的Sort方法。此外,如果在BinarySearch方法中使用IComparer<T>接口,必须对Sort方法传递一个一样的接口。否则,BinarySearch方法可能将无法找到目标对象。 |
示例3-4中的TestSort方法示范了怎样在List<Square>和SortedList<int,Square>集合的实例中使用Square类和CompareHeight类。
//示例3-4.让类型支持搜索
public static void TestSearch() { List<Square> listOfSquares = new List<Square> {new Square(1,3), new Square(4,3), new Square(2,1), new Square(6,1)}; IComparer<Square> heightCompare = new CompareHeight(); // Test a List<Square> Console.WriteLine("List<Square>"); Console.WriteLine("Original list"); foreach (Square square in listOfSquares) { Console.WriteLine(square.ToString()); } Console.WriteLine(); Console.WriteLine("Sorted list using IComparer<Square>=heightCompare"); listOfSquares.Sort(heightCompare); foreach (Square square in listOfSquares) { Console.WriteLine(square.ToString()); } Console.WriteLine(); Console.WriteLine("Search using IComparer<Square>=heightCompare"); int found = listOfSquares.BinarySearch(new Square(1, 3), heightCompare); Console.WriteLine("Found (1,3): " + found); Console.WriteLine(); Console.WriteLine("Sorted list using IComparable<Square>"); listOfSquares.Sort(); foreach (Square square in listOfSquares) { Console.WriteLine(square.ToString()); } Console.WriteLine("Search using IComparable<Square>"); found = listOfSquares.BinarySearch(new Square(6, 1)); // Use IComparable Console.WriteLine("Found (6,1): " + found); // Test a SortedList<Square> var sortedListOfSquares = new SortedList<int, Square>(){ {0, new Square(1,3)}, {2, new Square(4,3)}, {1, new Square(2,1)}, {4, new Square(6,1)}}; Console.WriteLine(); Console.WriteLine(); Console.WriteLine("SortedList<Square>"); foreach (KeyValuePair<int, Square> kvp in sortedListOfSquares) { Console.WriteLine(kvp.Key + " : " + kvp.Value); } Console.WriteLine(); bool foundItem = sortedListOfSquares.ContainsKey(2); Console.WriteLine("sortedListOfSquares.ContainsKey(2): " + foundItem); // Does not use IComparer or IComparable // -- uses a linear search along with the Equals method // which has not been overloaded Square value = new Square(6, 1); foundItem = sortedListOfSquares.ContainsValue(value); Console.WriteLine("sortedListOfSquares.ContainsValue(new Square(6,1)): " + foundItem); }
上述代码输出结果如下所示:
List<Square>
Original list
Height:1 Width:3
Height:4 Width:3
Height:2 Width:1
Height:6 Width:1
Sorted list using IComparer<Square>=heightCompare
Height:1 Width:3
Height:2 Width:1
Height:4 Width:3
Height:6 Width:1
Search using IComparer<Square>=heightCompare
Found (1,3): 0
Sorted list using IComparable<Square>
Height:2 Width:1
Height:1 Width:3
Height:6 Width:1
Height:4 Width:3
Search using IComparable<Square>
Found (6,1): 2
SortedList<Square>
0 : Height:1 Width:3
1 : Height:2 Width:1
2 : Height:4 Width:3
4 : Height:6 Width:1
sortedListOfSquares.ContainsKey(2): True
sortedListOfSquares.ContainsValue(new Square(6,1)): True
还可参见
3-2节;MSDN文档中“IComparable<T>接口”主题和“IComparer<T>接口”主题。
版权说明:作者:张颖希(PocketZ's Blog)
出处:http://www.cnblogs.com/PocketZ
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
本文翻译内容取自网络,纯粹是练习英文水平,如有雷同,纯属意外!有不妥之处,欢迎拍砖!