您的位置:首页 > 编程语言 > C#

C# 3.0 CookBook:三、类与结构(3):让类型支持搜索

2010-04-26 13:54 337 查看
问题

已有一个自定义类型可以像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.让类型支持搜索
[code]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
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

本文翻译内容取自网络,纯粹是练习英文水平,如有雷同,纯属意外!有不妥之处,欢迎拍砖!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: