1.a: 直接插入排序
假设待排序的记录存放在数组R[1..n]中。初始时,R[1]自成1个有序区,无序区为R[2..n]。从i=2起直至i=n为止,依次将R[i]插入当前的有序区R[1..i-1]中,生成含n个记录的有序区。每次从无序表中取出第一个元素,把它插入到有序表的合适位置,使有序表仍然有序。
一趟直接插入排序两种方法:
1.简单方法
首先在当前有序区R[1..i-1]中查找R[i]的正确插入位置k(1≤k≤i-1);然后将R[k..i-1]中的记录均后移一个位置,腾出k位置上的空间插入R[i]。
注意:
若R[i]的关键字大于等于R[1..i-1]中所有记录的关键字,则R[i]就是插入原位置。
2.改进的方法
一种查找比较操作和记录移动操作交替地进行的方法。
具体做法:
将待插入记录R[i]的关键字从右向左依次与有序区中记录R[j](j=i-1,i-2,…,1)的关键字进行比较:
① 若R[j]的关键字大于R[i]的关键字,则将R[j]后移一个位置;
②若R[j]的关键字小于或等于R[i]的关键字,则查找过程结束,j+1即为R[i]的插入位置。
关键字比R[i]的关键字大的记录均已后移,所以j+1的位置已经腾空,只要将R[i]直接插入此位置即可完成一趟直接插入排序
/// <summary> /// 对顺序表arr中的记录按递增序进行插入排序 /// int[] arr = { 99, 2, 13, 5, 75, 33, 10, 87, 55, 12, 1, 6, 34, 47 }; /// </summary> /// <param name="arr"></param> static void InsetSort1(int[] arr) { int i, j, pos; for (i = 1; i < arr.Length; i++) //依次插入arr[1],…,arr[n-1] { pos = 0; // 在有序表中,从右向左扫描,来确定插入项arr[i]的插入位置 for (j = i - 1; j >= 0; j--) { if (arr[i] >= arr[j]) { pos = j+1; break; } } // 将arr[i]插入到位置j if (i == pos) { continue; } else { int temp = arr[i]; for (j = i-1; j >= pos; j--) { arr[j + 1] = arr[j]; } arr[pos] = temp; } } } /// <summary> /// 对顺序表arr中的记录按递增序进行插入排序 /// int[] arr = { 99, 2, 13, 5, 75, 33, 10, 87, 55, 12, 1, 6, 34, 47 }; /// </summary> /// <param name="arr"></param> static void InsetSort2(int[] arr) { int i, j; for (i = 1; i < arr.Length; i++) // 依次插入arr[1],…,arr[n-1] { // 在有序表中,从右向左扫描,若arr[j]的关键字大于arr[i]的关键字,则将arr[j]后移一个位置; int temp = arr[i]; for (j = i - 1; j >= 0; j--) { if (arr[j] > temp) { arr[j + 1] = arr[j]; arr[j] = temp; } } } }
1.b 希尔排序
希尔排序(Shell Sort)是插入排序的一种。因D.L.Shell于1959年提出而得名。基本思想:
先取一个小于n的整数d1作为第一个增量,把文件的全部记录分成d1个组。所有距离为dl的倍数的记录放在同一个组中。先在各组内进行直接插人排序;然后,取第二个增量d2<d1重复上述的分组和排序,直至所取的增量dt=1(dt<dt-l<…<d2<d1),即所有记录放在同一组中进行直接插入排序为止。该方法实质上是一种分组插入方法。
在希尔排序中首先解决的是子序列的选择问题。对于子序列的构成不是简单的分段,而是采取相隔某个增量的数据组成一个序列。一般的选择原则是:用上一个增量的一半作为此次序列的划分增量。首次选择序列长度的一半为增量。
/// <summary> /// 希尔排序算法的实现 /// </summary> /// <param name="arr"></param> static void ShellSort(int[] arr) { int d = arr.Length / 2; // 设置希尔排序的增量 int i, j, temp; while (d >= 1) { for (i = d; i < arr.Length; i++ ) { temp = arr[i]; j = i - d; while (j >=0 && arr[j] > temp) { arr[j + d] = arr[j]; arr[j + d] = temp; j = j - d; } } d = d / 2; //缩小增量 } }
2.a:冒泡排序
比较相邻的元素。如果第一个比第二个大,就交换他们两个。持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
/// <summary> /// 对顺序表arr中的记录按递增序进行插入排序 /// int[] arr = { 99, 2, 13, 5, 75, 33, 10, 87, 55, 12, 1, 6, 34, 47 }; /// </summary> /// <param name="arr"></param> static void BubbleStort(int[] arr) { // arr是待排序的数组,采用自后向前扫描,对arr做冒泡排序 bool exchangeFlag; //交换标志 for (int i = 1; i < arr.Length; i++) // 最多做n-1趟排序 { exchangeFlag = false; //本趟排序开始前,交换标志应为假 for (int j = arr.Length - 1; j >= i; j--) //对当前无序区arr[i..j]自后向前扫描 { if (arr[j] < arr[j - 1]) //交换记录 { int temp = arr[j]; arr[j] = arr[j - 1]; arr[j - 1] = temp; exchangeFlag = true; //发生了交换,故将交换标志置为真 } } if(!exchangeFlag) { //本趟排序未发生交换,说明从本趟开始,剩下的arr[i...j]有序的,提前终止算法 break; } } }
快速排序(Quicksort)是对冒泡排序的一种改进。由C. A. R. Hoare在1962年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
步骤:设有一待排序的序列
1.分别设置low、hight指向序列的最左端、最右端;从序列中选一个进行排序(通常选最左端的值low指向的值),存入到tmp;
2.从hight端开始,查找比tmp小的,找到后讲该值放入到low指向的存储位中;同时将hight指向当前查到的值所在的位;
3.从low端开始,查找比tmp大的,找到后将该值放入到hight指向的存储为中,同时low指向当前查到的值所在位;
4.若low位小于hight位,返回2步;否则,将tmp值存入到空出来的low+1指向的位置,退出,返回low所在的位置lposition。
5.以lposition为界,将序列分成两部分,分别对两部分进行排序。
static void QuickSort(int[] arr) { QuickSort(arr, 0, arr.Length - 1); } /// <summary> /// 快速排序算法C#实现 /// </summary> static void QuickSort(int[] arr, int left, int right) { if (arr == null || left < 0 || left >= right || right >= arr.Length) { return; } int i = left; int j = right; // 从数组两端交替地向中间扫描 if (left <= right) { // 设置基准值 int key = arr[left]; // 进行扫描的指针i,j;i从左边开始,j从右边开始 while (i < j) { // 右 while (i < j && arr[j] > key) { j--; } if (i < j) { // 比枢纽元素小的移动到左边 arr[i] = arr[j]; i++; } // 左 while (i < j && arr[i] < key) { i++; } if (i < j) { // 比枢纽元素大的移动到右边 arr[j] = arr[i]; j--; } } // 枢纽元素移动到正确位置 arr[i] = key; // 表递归排序 QuickSort(arr, left, i - 1); QuickSort(arr, i + 1, right); } }
3.a 直接选择排序
直接选择排序(Straight Select Sorting) 也是一种简单的排序方法,它的基本思想是:第一次从R[0]~R[n-1]中选取最小值,与R[0]交换,第二次从R[1]~R[n-1]中选取最小值,与R[1]交换,....,
第i次从R[i-1]~R[n-1]中选取最小值,与R[i-1]交换,.....,第n-1次从R[n-2]~R[n-1]中选取最小值,与R[n-2]交换,总共通过n-1次,得到一个按排序码从小到大排列的有序序列.
static void SelectSort(int[] arr) { for (int i = 0; i < arr.Length-1; i++ ) { int minIndex = i; for (int j = i + 1; j < arr.Length; j++ ) { if (arr[j] < arr[minIndex]) { minIndex = j; } } if (minIndex != i) { int temp = arr[i]; arr[i] = arr[minIndex]; arr[minIndex] = temp; } } }