public class InsertionSorter public void Sort(int[] arr) for (int i = 1; i < arr.Length; i++) int t = arr[i]; int j = i; while ((j > 0) && (arr[j - 1] > t)) arr[j] = arr[j - 1];//交换顺序 –j; arr[j] = t;
希尔排序 希尔排序基本思想: 先取一个小于n的整数d1作为第一个增量,把文件的全部记录分成d1个组。所有距离为dl的倍数的记录放在同一个组中。先在各组内进行直接插入排序;然后,取第二个增量d2 public class ShellSorter public void Sort(int[] arr) int inc; for (inc = 1; inc <= arr.Length / 9; inc = 3 * inc + 1) ; for (; inc > 0; inc /= 3) for (int i = inc + 1; i <= arr.Length; i += inc) int t = arr[i - 1]; int j = i; while ((j > inc) && (arr[j - inc - 1] > t)) arr[j - 1] = arr[j - inc - 1];//交换数据 j -= inc; arr[j - 1] = t;
无序的数组 /// 有序数组 /// Lihua() int[] Sort(int[] data) //取数组中间下标 int middle = data.Length / 2; //初始化临时数组let,right,并定义result作为最终有序数组 int[] left = new int[middle], right = new int[middle], result = new int[data.Length]; if (data.Length % 2 != 0)//若数组元素奇数个,重新初始化右临时数组 right = new int[middle + 1]; if (data.Length <= 1)//只剩下1 or 0个元数,返回,不排序 return data; int i = 0, j = 0; foreach (int x in data)//开始排序 if (i < middle)//填充左数组 left[i] = x; i++; else//填充右数组 right[j] = x; j++; left = Sort(left);//递归左数组 right = Sort(right);//递归右数组 result = Merge(left, right);//开始排序 //this.Write(result);//输出排序,测试用(lihua debug) return result; ///
/// 归并排序之并:排序在这一步 ///
///
左数组 ///
右数组 /// 合并左右数组排序后返回 int[] Merge(int[] a, int[] b) //定义结果数组,用来存储最终结果 int[] result = new int[a.Length + b.Length]; int i = 0, j = 0, k = 0; while (i < a.Length && j < b.Length) if (a[i] < b[j])//左数组中元素小于右数组中元素 result[k++] = a[i++];//将小的那个放到结果数组 else//左数组中元素大于右数组中元素 result[k++] = b[j++];//将小的那个放到结果数组 while (i < a.Length)//这里其实是还有左元素,但没有右元素 result[k++] = a[i++]; while (j < b.Length)//右右元素,无左元素 result[k++] = b[j++]; return result;//返回结果数组 注:此算法由周利华提供( ) 基数排序 基数排序法又称“桶子法”(bucket sort)或bin sort,顾名思义,它是透过键值的部份资讯,将要排序的元素分配至某些“桶”中,藉以达到排序的作用,基数排序法是属于稳定性的排序,其时间复杂度为O (nlog(r)m),其中r为所采取的基数,而m为堆数,在某些时候,基数排序法的效率高于其它的比较性排序法。 //基数排序 public int[] RadixSort(int[] ArrayToSort, int digit) //low to high digit for (int k = 1; k <= digit; k++) //temp array to store the sort result inside digit int[] tmpArray = new int[ArrayToSort.Length]; //temp array for countingsort int[] tmpCountingSortArray = new int[10]0,0,0,0,0,0,0,0,0,0; //CountingSort for (int i = 0; i < ArrayToSort.Length; i++) //split the specified digit from the element int tmpSplitDigit = ArrayToSort[i]/(int)Math.Pow(10,k-1) - (ArrayToSort[i]/(int)Math.Pow(10,k))*10; tmpCountingSortArray[tmpSplitDigit] += 1; for (int m = 1; m < 10; m++) tmpCountingSortArray[m] += tmpCountingSortArray[m - 1]; //output the value to result for (int n = ArrayToSort.Length - 1; n >= 0; n–) int tmpSplitDigit = ArrayToSort[n] / (int)Math.Pow(10,k – 1) – (ArrayToSort[n]/(int)Math.Pow(10,k)) * 10; tmpArray[tmpCountingSortArray[tmpSplitDigit]-1] = ArrayToSort[n]; tmpCountingSortArray[tmpSplitDigit] -= 1; //copy the digit-inside sort result to source array for (int p = 0; p < ArrayToSort.Length; p++) ArrayToSort[p] = tmpArray[p]; return ArrayToSort; 计数排序 数排序, 基数排序, 桶排序等非比较排序算法,平均时间复杂度都是O(n). 这些排序因为其待排序元素本身就含有了定位特征,因而不需要比较就可以确定其前后位置,从而可以突破比较排序算法时间复杂度O(nlgn)的理论下限. 计数排序是最简单的特例,它要 求待排序元素是位于0到k之间的正整数 , 因而它是很特殊的情况,基本上没有特别的应用价值; 但是另一方面, 它又是基数排序的基础,或者说是一部分,所以简单的描述一下: 输入数组 A : 元素特征是 0-k的正整数,可以有重复值; 输出数组 B : 输出A的一个非减序列 中间数组 C : 大小是k, 它的i( 0<= i <= k)索引位置存储的是A元素集合中值是k的元素的个数有关. 算法的基本思想是: 统计A中元素的值的集合, 以A中元素的值为索引, 将值的个数填写到中间数组C的对应处. 对C从头开始自累加, 这样C中存储的就是, 当输入数组A中的值为当前索引时, 它前面的元素数量(包含重复元素). 将C依次输出到输出数组B中. ///
/// counting sort ///
///
input array ///
the value arrange in input array /// public int[] CountingSort(int[] arrayA, int arrange) //array to store the sorted result, //size is the same with input array. int[] arrayResult = new int[arrayA.Length]; //array to store the direct value in sorting process //include index 0; //size is arrange+1; int[] arrayTemp = new int[arrange+1]; //clear up the temp array for(int i = 0; i <= arrange; i++) arrayTemp[i] = 0; //now temp array stores the count of value equal for(int j = 0; j < arrayA.Length; j++) arrayTemp[arrayA[j]] += 1; //now temp array stores the count of value lower and equal for(int k = 1; k <= arrange; k++) arrayTemp[k] += arrayTemp[k - 1]; //output the value to result for (int m = arrayA.Length-1; m >= 0; m–) arrayResult[arrayTemp[arrayA[m]] – 1] = arrayA[m]; arrayTemp[arrayA[m]] -= 1; return arrayResult; 根堆排序 堆排序是一种树形选择排序,在排序过程中,将A[n]看成是完全二叉树的顺序存储结构,利用完全二叉树中双亲结点和孩子结点之间的内在关系来选择最小的元素。
堆排序是不稳定的。算法时间复杂度O(nlog n)。 ///
/// 小根堆排序 ///
///
///
///
private void HeapSort(ref double[] dblArray) for (int i = dblArray.Length – 1; i >= 0; i–) if (2 * i + 1 < dblArray.Length) int MinChildrenIndex = 2 * i + 1; //比较左子树和右子树,记录最小值的Index if (2 * i + 2 < dblArray.Length) if (dblArray[2 * i + 1] > dblArray[2 * i + 2]) MinChildrenIndex = 2 * i + 2; if (dblArray[i] > dblArray[MinChildrenIndex])