排序之插入排序(简单插入排序,希尔排序)
插入排序:
阐述:
在已排序集合中插入待排序集合中的某一元素,使得已排序集合仍然有序,直到待排序集合大小为1。
时间复杂度:
插入已排序集合的时间复杂度是O(N),遍历待排序集合的时间复杂度是O(N),所以插入排序的时间复杂度是O(N*N)。
稳定性
插入排序主要就是在挪动待排序集合的位置,并且将元素插入到合适位置,不会打乱相同元素的相对位置,所以是稳定的。
效果图:
代码(c#):
/// <summary> /// 插入排序 /// </summary> public static void DoInsertionSort() { List<int> listNum = new List<int>() { 3, 10, 11, 2, 6, 4, 2, 17, 19 }; //两层循环,外循环是遍历未排序集合,内循环用来遍历已排序集合 for (int indexUnOrder = 1; indexUnOrder < listNum.Count; indexUnOrder++) { int itemInsert = listNum[indexUnOrder]; int indexOrdered = indexUnOrder - 1; //遍历已排序集合 while (indexOrdered > -1 && itemInsert < listNum[indexOrdered]) //itemInsert==listNum[j]的情况没有写进去,使得插排算法是稳定的 { listNum[indexOrdered + 1] = listNum[indexOrdered]; //向后挪动元素 indexOrdered--; } //j 指向要插入的位置 listNum[indexOrdered + 1] = itemInsert; //LogWrite.LogPlain(DisplayList(listNum, new List<int> { j+1},'<','>')); } }
希尔排序
阐述:
使用增量d对集合进行分组(也就是索引相隔d个元素的数放在一组),然后在组内进行插入排序,有节奏地缩小增量d,然后再进行组内插入排序,如此往复,直到增量d为1(也就是把集合分为一个组)。
算法描述:
1.按照增量d分组
2.遍历所有分组,并进行组内插入排序
3.减小增量d,如果d不小于1,回到第1步,
时间复杂度:
增量的递减复杂度是O(lgN),分组的遍历(按照增量d的位置开始遍历)和组内数组的移动(按照增量d的跨度挪动),这个复杂度据说暂时没有说法,只是说,比插入排序O(N*N)好。
稳定性:
分组进行的组内移动能保证稳定,但是组与组之间没有约束,很容易改变相同元素的相对位置,所以希尔排序是不稳定的。
算法关键字:
增量,分组,插入排序
效果图:
代码(c#):
/// <summary> /// 希尔排序 /// </summary> public static void DoShellSort() { List<int> listNum = new List<int>() { 25, 19, 6, 58, 34, 10, 7, 98, 160, 0 }; int indexIncreasement = listNum.Count / 2; //设置希尔排序的增量索引 int indexGroup; //遍历分组的索引 int indexGroupItem; //指向分组项的索引 int temp; //LogWrite.LogPlain("排序的数据如下:"); //LogWrite.LogPlain(DisplayList(listNum)); //遍历增量 while (indexIncreasement >= 1) { LogWrite.LogPlain(string.Format("增量是:{0}", indexIncreasement)); //遍历分组 for (indexGroup = indexIncreasement; indexGroup < listNum.Count; indexGroup++) //indexI 用来遍历分组 { temp = listNum[indexGroup]; indexGroupItem = indexGroup - indexIncreasement; //在分组内插入数据 while (indexGroupItem >= 0 && listNum[indexGroupItem] > temp) { //LogWrite.LogPlain(DisplayList(listNum, new List<int> { indexGroupItem + indexIncreasement, indexGroupItem }, '<', '>')); listNum[indexGroupItem + indexIncreasement] = listNum[indexGroupItem]; indexGroupItem -= indexIncreasement; } listNum[indexGroupItem + indexIncreasement] = temp; //if (indexGroupItem < 0) // indexGroupItem = indexGroupItem + indexIncreasement; //LogWrite.LogPlain(DisplayList(listNum, new List<int>() { indexGroup, indexGroupItem })); } indexIncreasement = indexIncreasement / 2; //缩小增量 } }