构建可反转排序的泛型字典类(2)--排序方向

2. 排序方向

你希望ReversibleSortedList类中的元素是以TKey(键)的顺序进行存储的,并且它即可以从小排到大,也可以从大排到小。当然,最佳方式就是在添加元素时找到合适的位置插入,插入后元素就已经按顺序排好。在一个有序数组中查找合适的插入点这样的算法并不困难,但FCL已经帮我们实现了,而且是采用速度最快的二分查找法(在MSDN中被称为“二进制搜索法”)。太棒了!它就是:静态方法Array.BinarySearch。下面我们来看MSDN中对它的介绍。

Array.BinarySearch一共有8个重载版本,最后一个是我们需要的:

public static int BinarySearch<T> (
  T[] array, //要搜索的从零开始的一维排序 Array
  int index, //要搜索的范围的起始索引。
  int length, //要搜索的范围的长度。
  T value, //要搜索的对象。
  IComparer<T> comparer //比较元素时要使用的 IComparer 实现。
)

其中,T表示数组元素的类型。对返回值的介绍是:如果找到 value,则为指定 array 中的指定 value 的索引。如果找不到 value 且 value 小于 array 中的一个或多个元素,则为一个负数,该负数是大于 value 的第一个元素的索引的按位求补。如果找不到 value 且 value 大于 array 中的任何元素,则为一个负数,该负数是最后一个元素的索引加 1的按位求补。

我们的ReversibleSortedList不能插入重复的键值。当返回值大于或等于0时,表明不能插入。当返回值小于零时,表明没有找到重复键,而且这时返回值还带有插入位置的信息。考虑得可真周到啊,赞一个!

求补是什么呢?就是把二进制数的0变成1,1变成0。对于int来说,由于它是有符号整数,求补会把正数变为负数,把负数变为正数。对一个数进行两次求补运算就会得到原来的数。哈哈,如果反回值小于0,对它求补就可以得到插入位置信息了。真是得来全不费工夫!

现在的问题是需要一个实现了IComparer<T>接口的类。可以在ReversibleSortedList声明一个嵌套类以解决这个问题。当然,在实现IComparer<T>接口的Compare方法时在里面做些手脚就可以实现正向和反向排序了。这时需要一个能表示正向和反向排序的东西,FCL里有现成的,它就是System.ComponentModel命名空间下的 ListSortDirection枚举。它有两个值:Ascending表示升序,Descending表示降序。下面的代码在1.0版本的基础上添加了实现IComparer<T>接口的内部类:SortDirectionComparer<T>。代码可直接拷贝运行,运行它纯粹是为了检查是否有错误,没有什么看得见的效果。

时间: 2024-09-19 04:07:31

构建可反转排序的泛型字典类(2)--排序方向的相关文章

构建可反转排序的泛型字典类(1)--雏形

构建可反转排序的泛型字典类 前言 前段时间为了查找泛型资料,我翻译了O'Reilly 出版的<C# Cookbook>这本书的几个关于泛型的章节.其中"4.8 反转Sorted List里的内容"(见 http://cgbluesky.blog.163.com/blog/static/2412355820081211016581/ )这一节中有一个接近1300行代码的例子.当时看到这个例子吓了一跳,这是一个足以让人头晕眼花的数字.粗略看了一下,感觉代码质量非常高,非常值得我

构建可反转排序的泛型字典类(9完)--完善

9. 完善 大楼已经盖好,剩下的工作就是装修,装修好就可以入住了 .从本文的题目得知,这是一个可反转排序的集合类,但我们只实现了降序插入 功能,如果希望把升序转换为降序该怎么办呢?此例的解决方法是声明一个代表 排序方向的属性Comparer,并加入一个sort方法,调用sort方法时根据Comparer 属性进行排序: private ListSortDirection _currentSortDirection = ListSortDirection.Descending; public So

构建可反转排序的泛型字典类(7)--实现IDictionary接口

7. 实现IDictionary接口 前面做了很多努力,现在终于可以实现 IDictionary接口了.当然,之所以要先实现它,目的之一还是为了之前留下的 一点遗憾:在foreach中使用DictionaryEntry访问集合中的元素. 需要 注意,由于ReversibleSortedList类最主要的接口是泛型IDictionary接口,实 现非泛型IDictionary接口主要是考虑到兼容性,试想,你的项目是用.NET 1.0 实现的,但现在你需要使用.NET 2.0继续完善程序并使用到了一

构建可反转排序的泛型字典类(3)--实现元素添加及自动扩展

3. 实现元素添加及自动扩展 您是一单位CEO,单位占地50亩,这几年在你的带领下,公司不断发展壮大,原来50亩地已经不够用.公司急需扩大地盘,这个现实问题摆在你面前,该怎么办?到旁边单位抢地?不行,现在是法制社会.有两个解决方案,第一是买一块50亩的地,这样你的公司就有两个办公地点,缺点是不能统一管理,两个地点的员工交流不顺畅.第二是买一块100亩的地,把原来的地卖掉,公司全部搬到新地点.这样做的缺点是重建费用太大. 我们要构建的ReversibleSortedList集合也面临着这样的问题,

构建可反转排序的泛型字典类(8)--实现IDictionary接口

8. 实现IDictionary<TKey, TValue>接口 由于前面实现了 IDictionary接口,现在实现IDictionary<TKey, TValue>也就没什么困难 的了,照葫芦画瓢. 首先改变类声明: public class ReversibleSortedList<TKey, TValue> :IDictionary<TKey, TValue> IDictionary, IEnumerable<KeyValuePair<T

构建可反转排序的泛型字典类(5)--实现IEnumerable接口

5. 实现IEnumerable<KeyValuePair<TKey, TValue>>接口 我们先来看看ReversibleSortedList类的定义: public class ReversibleSortedList<TKey, TValue> : IDictionary<TKey, TValue>, ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValu

构建可反转排序的泛型字典类(4)--IDictionary接口

C#对集合类型有统一的规范.它的好处不言而喻,所有集合类都有一些统一的调用方法和属性,这使得学习成本大大降低.统一的规范就是通过接口来实现的(关于接口,如果不熟,请参考 http://www.enet.com.cn/eschool/video/c/30.shtml ),另一方面一些类也会直接调用这些标准接口,使得我们写出来的类有更好的兼容性.最典型的例子莫过于IEnumerable接口,只要实现了它就可以使用foreach语句进行调用. 我们将要给ReversibleSortedList实现的是

构建可反转排序的泛型字典类(6)--实现IDictionary接口中的Keys和Values属性

6. 实现IDictionary接口中的Keys和Values属性 现在我们可以着眼于IDictionary接口的实现.第4节中,专门针对这个接口做了一 个最简化的例子,我们来回顾一下,它是怎么实现IDictionary接口中的Keys和Values属性的. public ICollection Keys { //返回所有键的集合 get { //把所有键的集合拷贝到新数组中并返回 Object[] keys = new Object[ItemsInUse]; for (Int32 n = 0;

python的sorted函数对字典按key排序和按value排序

1.sorted函数按key值对字典排序 先来基本介绍一下sorted函数,sorted(iterable,key,reverse),sorted一共有iterable,key,reverse这三个参数. 其中iterable表示可以迭代的对象,例如可以是 dict.items().dict.keys()等,key是一个函数,用来选取参与比较的元素,reverse则是用来指定排序是倒序还是顺 序,reverse=true则是倒序,reverse=false时则是顺序,默认时reverse=fal