复习八大基础排序算法。分类:
1. 插入类(直接插入、希尔排序)
2. 选择类(直接选择、堆排序)
3. 交换类(冒泡排序、快速排序)
4. 归并排序
5. 还有外部排序(桶排序?)
直接插入
首先明确定义,比如插入排序如果对定义不够清楚,有可能写着写着就掺和进了选择排序(排序结果不一定错,但是过程“变质了”)。
直接插入排序(Insertion Sort)的基本思想是:每次将一个待排序的记录,按其关键字大小插入到前面已经排好序的子序列中的适当位置,直到全部记录插入完成为止。
设数组为a[0…n-1]。
-
初始时,a[0]自成1个有序区,无序区为a[1..n-1]。令i=1
-
将a[i]并入当前的有序区a[0…i-1]中形成a[0…i]的有序区间
-
i++并重复第二步直到i==n-1。排序完成
下面给出严格按照定义书写的代码(由小到大排序):
public static void insertionSort1(Comparable[] a) {
for (int i = 1; i < a.length; i++) {
// search
int j;
for (j = i - 1; j >= 0; j--)
if (less(a[j], a[i])) break; // a[j] < a[i]
// insert (shift then put)
if (j != i - 1) {
Comparable temp = a[i];
for (int k = i; k > j + 1; k--)
a[k] = a[k - 1];
a[j + 1] = temp;
}
}
}
这个代码比较长,可以进行改写,将搜索和数据后移两个步骤合并。即:用temp记录a[i]的值,每次a[j]都和a[i]比较,如果a[i] < a[j]说明a[0…i]也是有序的,无须调整;否则就一边将数据a[j]后移一边向前搜索,直到a[j]<a[i]才停止,并将temp放到a[j+1]处。
public static void insertionSort2(Comparable[] a) {
for (int i = 1; i < a.length; i++) {
// insert while search
Comparable temp = a[i];
int j;
for (j = i - 1; j >= 0 && less(a[i], a[j]); j--) {
a[j + 1] = a[j];
}
a[j + 1] = temp;
}
}
再对将a[i]插入到前面a[0…i-1]的有序区间所用的方法进行改写,用数据交换
代替数据后移
。如果a[j]前一个数据a[j-1] > a[j],就交换a[j]和a[j-1],再j--直到a[j-1] <= a[j]。这样也可以实现将一个新数据新并入到有序区间。
public static void insertionSort3(Comparable[] a) {
for (int i = 1; i < a.length; i++) {
for (int j = i - 1; j >= 0 && less(a[j+1], a[j]); j--)
exch(a, j, j+1);
}
}
希尔排序
public static void shellSort1(Comparable[] a) {
int[] incs = {33936, 13776, 4592, 1968, 861, 336, 112, 48, 21, 7, 3, 1};
for (int d = 0; d < incs.length; d++) {
int h = incs[d];
if (a.length > h) {
for (int k = 0; k < h; k++) {
/*
* 对每一组作直接插入排序( insertionSort 只有一组,对应的 h = 1, k = 0 )
*/
for (int i = k + h; i < a.length; i += h)
for (int j = i - h; j >= k && less(a[j + h], a[j]); j -= h)
exch(a, j + h, j);
}
}
}
}
public static void shellSort2(Comparable[] a) {
int[] incs = {33936, 13776, 4592, 1968, 861, 336, 112, 48, 21, 7, 3, 1};
for (int d = 0; d < incs.length; d++) {
int h = incs[d];
if (a.length > h) {
for (int i = h; i < a.length; i++)
for (int j = i - h; j >= 0 && less(a[j + h], a[j]); j -= h)
exch(a, j + h, j);
}
}
}