算法思路:(此算法为从大到小,可更改) 不断把数组的区间一分为二,使两端逐渐逼近与目标数近似的数,找到目标数的要插入的位置。
若插入的数是已存在需更新的,得到它原先的排序号index。先将其从数组删除,找到其区间方向(新值>旧值,则区间为[0,index];否则为[index,length(数组长度-1)]),开始进行查找。
如何通用:重点在于各种要对比大小的对象类型可能不一样,如果用>,<判断肯定是不够的,因此可以传一个委托进来,进行大小判断。传入两个参数(A,B)若A>B,则返回true ,反之则为false,若都不是A=B。
具体实现:
/// <summary> /// 通用的降序插入算法 /// </summary> /// <param name="sortList">插入目标链表</param> /// <param name="obj">插入对象</param> /// <param name="CompareFun">比较方式</param> /// <param name="index">若已经存在要变值,为原对象的index</param> public static void DivideInsert<T>(ref List<T> sortList,T obj,Func<T,T,bool> CompareFun,int index=-1) { if(index!=-1) { sortList.RemoveAt(index); } //数组长度 int count=sortList.Count;
//中间数序号,[lowidx,highidx]区间两端序号 int middle,lowidx=0,highidx=count-1;
//obj和在最后比较出middle数的左边还是右边,不太好理解,具体看一下算法 int dir=0;
//需更新对象在list中的原序号 if (index!=-1) { if (CompareFun(obj,sortList[index])) { highidx=index; }else { lowidx=index; } }
//若list为空,直接加 if (count==0) { sortList.Add(obj); return; } //循环找出obj要插入的位置序号 while(true) { middle=(lowidx+highidx)/2; if (CompareFun(obj,sortList[middle])) { dir=0; highidx=middle-1; if(highidx<0) { break; } if(CompareFun(sortList[highidx],obj)) { break; } }else if (CompareFun(sortList[middle],obj)) { dir=1; lowidx=middle+1; if(lowidx>count-1) { break; } if(CompareFun(obj,sortList[lowidx])) { break; } } else { dir=0; middle=middle+1; break; } } sortList.Insert(middle+dir,obj); }