如果说不考虑自定义编码逻辑的前提下,促使我们在对集合新增或修改元素后让集合有序排列,最傻最简单的做法就是.Net类库自带的Sort方法。
对于新增
当然有些杠精会说,我在新增元素的同时指定元素的位置不就行了嘛,但是这个操作需要人为的判断,我们需要知道集合的顺序,需要拿新元素和现有数据进行比对,才能知道插入在那里。
如下面代码,我知道集合的数据内容并且知道插入的元素指具体是多少,我才知道7要插在9的前面。如果在集合数据量大且不知道新增元素具体值的情况下,这样的逻辑就很难实现。
对于修改
修改集合某个元素的数值,则可能直接会导致List集合的顺序发生变化,所以排序操作是毋庸置疑的,而本文要实现的是,在修改方法的同时就实现了对集合的排序,也就无需使用List.Sort方法,这也避免了Sort带来程序另外的开销。
实现代码
1 public class SortedList<T>:List<T> 2 { 3 public new void Add(T item) 4 { 5 //查询新元素在现有集合中的位置 6 int position = this.BinarySearch(item); 7 8 //如果小于0则表示,元素在集合中不存在 9 if (position<0) 10 { 11 position = ~position; //使用“按位求补运算符”确定新元素的插入位置 12 } 13 this.Insert(position,item); 14 } 15 16 public void ModifySorted(T item,int index) 17 { 18 this.RemoveAt(index); 19 20 int position = this.BinarySearch(item); 21 if (position<0) 22 { 23 position = ~position; 24 } 25 this.Insert(position, item); 26 27 } 28 29 30 }
调用场景
1 //创建一个SortedList并随机选择的数值填充 2 SortedList<int> sortedList = new SortedList<int>(); 3 sortedList.Add(200); 4 sortedList.Add(20); 5 sortedList.Add(2); 6 sortedList.Add(7); 7 sortedList.Add(10); 8 sortedList.Add(0); 9 sortedList.Add(100); 10 sortedList.Add(-20); 11 sortedList.Add(56); 12 sortedList.Add(55); 13 sortedList.Add(57); 14 sortedList.Add(200); 15 sortedList.Add(-2); 16 sortedList.Add(-20); 17 sortedList.Add(55); 18 sortedList.Add(55); 19 20 21 foreach (var i in sortedList) 22 { 23 Console.WriteLine(i); 24 } 25 26 //修改指定索引的值 27 sortedList.ModifySorted(0, 5); 28 sortedList.ModifySorted(1, 10); 29 sortedList.ModifySorted(2, 11); 30 sortedList.ModifySorted(3, 7); 31 sortedList.ModifySorted(4, 2); 32 sortedList.ModifySorted(2, 4); 33 sortedList.ModifySorted(15, 0); 34 sortedList.ModifySorted(0, 15); 35 sortedList.ModifySorted(223, 15); 36 37 Console.WriteLine(); 38 foreach (var i in sortedList) 39 { 40 Console.WriteLine(i); 41 }
实现分析
通过本文的技巧实现了在对List集合新增获取修改的同时自动的实现了集合的有序排列。则无需再另行调用List.Sort方法来实现排序,这样会带来另外的性能消耗。
算法的精髓就在于BinarySearch函数和“按位求补运算符~”的妙用。
BinarySearch方法基于内部的算法逻辑会得出一个正数和负数。
如果返回的是正数,则表示集合内存在相同的元素,则返回值就是相同元素的索引位置,然后使用List.Insert方法就会将新元素插入到相同元素的前一位(类似于分组插入的抽象逻辑)
如果返回的是负数,基于BinarySearch逻辑并使用“按位求补运算符~”,就可以将新元素有序的插入到指定位置,其有序排列核心关键还是在于BinarySearch的算法逻辑,只不过配合“按位求补运算符~”的妙用,促使新元素始终有序插入。
心得
本来一个Sort可以解决的事情,都可以牵引出来这么巧妙的运用,我想这就是编程的魅力所在。