问题:
你将使用List<T>的BinarySearch方法定期查找List<T>中的特定元素。在查找过程中,将穿插进行添加、修改和删除的操作。不过,BinarySearch方法预先假设数组是有序的。如果List<T>是无序的,BinarySearch方法可能返回不正确的结果。你不希望必须记住在调用List<T>.BinarySearch方法之前调用List<T>.Sort方法。更不必说会引入与该调用关联的所有开销。你需要采用一种方法保持List<T>有序,而不必总是调用List<T>.Sort方法。
解决方案:
下面SortedList泛型类增强了在List<T>内添加和修改元素的操作。在向其添加数据项或修改数据项时,这些方法可以保持数组有序。注意,这里并不需要DeleteSorted方法,因为删除数据项不会干扰剩余数据项的排序顺序。
public class SortedList<T> : List<T>
{
public new void Add(T item)
{
int position = this.BinarySearch(item);
if (position < 0)
position = ~position;
this.Insert(position, item);
}
public void ModifySorted(T item, int index)
{
this.RemoveAt(index);
int position = this.BinarySearch(item);
if (position < 0)
position = ~position;
this.Insert(position, item);
}
}
讨论:
在保持List<T>有序的同时使用Add方法添加元素。Add方法接受一个泛型类型(T)以添加到有序列表中。
不要直接使用List<T>索引器修改元素,而是使用ModifySorted方法修改元素,同时保持List<T>有序。调用这个方法,传入泛型类型T以替换现有的对象(item),并且传入要修改对象的索引(index)。
下面的代码演示了SortedList<T>类:
public static void TestSortedList()
{
// Create a SortedList and populate it with
// randomly choosen numbers
SortedList<int> sortedList = new SortedList<int>();
sortedList.Add(200);
sortedList.Add(20);
sortedList.Add(2);
sortedList.Add(7);
sortedList.Add(10);
sortedList.Add(0);
sortedList.Add(100);
sortedList.Add(-20);
sortedList.Add(56);
sortedList.Add(55);
sortedList.Add(57);
sortedList.Add(200);
sortedList.Add(-2);
sortedList.Add(-20);
sortedList.Add(55);
sortedList.Add(55);
// Display it
foreach (var i in sortedList)
Console.WriteLine(i);
// Now modify a value at a particular index
sortedList.ModifySorted(0, 5);
sortedList.ModifySorted(1, 10);
sortedList.ModifySorted(2, 11);
sortedList.ModifySorted(3, 7);
sortedList.ModifySorted(4, 2);
sortedList.ModifySorted(2, 4);
sortedList.ModifySorted(15, 0);
sortedList.ModifySorted(0, 15);
sortedList.ModifySorted(223, 15);
// Display it
Console.WriteLine();
foreach (var i in sortedList)
Console.WriteLine(i);
// Doing it the hard way
List<int> testList = new List<int>();
testList.Add(200);
testList.Sort();
testList.Add(20);
testList.Sort();
testList.Add(2);
testList.Sort();
testList.Add(7);
testList.Sort();
testList.Add(10);
testList.Sort();
testList.Add(0);
testList.Sort();
testList.Add(100);
testList.Sort();
testList.Add(-20);
testList.Sort();
testList.Add(56);
testList.Sort();
testList.Add(55);
testList.Sort();
testList.Add(57);
testList.Sort();
testList.Add(200);
testList.Sort();
}
该方法在保持List<T>排序顺序的同时自动把新数据项置于其中;执行该操作时,无需显式调用List<T>.Sort。其原因是,Add方法首先调用BinarySearch方法,并把要添加到List<T>中的对象传递给它。BinarySearch方法将返回在其中找到相同数据项的索引或者返回一个负数,可以用返回值来确定查找的数据项应该位于什么位置。如果BinarySearch方法返回一个正数,就可以使用List<T>.Insert方法在那个位置插入一个新元素,保持List<T>内的排序顺序。如果BinarySearch方法返回一个负数,就可以使用按位求补运算符~来确定数据项应该位于什么位置,假定它存在于一个有序列表中。使用这个数字,可以使用List<T>.Insert方法把数据项添加到有序列表中的正确位置,同时保持正确的排序顺序。
可以在不干扰排序顺序的情况下从有序列表中删除元素,但是在List<T>中修改元素的值则极有可能导致有序列表变得无序。ModifySorted方法缓解了这个问题。该方法的工作方式类似于Add方法,只不过它首先从List<T>中删除元素,然后把新元素插入正确的位置。
参考:
MSDN文档中的"List<T>类”主题。