排序算法模板
public abstract class Sort {
// 排序代码
public abstract void sort(Comparable[] a);
// 辅助函数:比较元素
protected static boolean less(Comparable c1, Comparable c2) {
return c1.compareTo(c2) < 0;
}
// 辅助函数:交换元素
protected static void exch(Comparable[] a, int i, int j) {
Comparable t = a[i];
a[i] = a[j];
a[j] = t;
}
// 打印数组
protected static void show(Comparable[] a) {
for (int i = 0; i < a.length; i++) {
System.out.print(a[i] + " ");
}
System.out.println();
}
// 是否有序
protected static boolean isSorted(Comparable[] a) {
for (int i = 1; i < a.length; i++) {
if (less(a[i], a[i - 1])) {
return false;
}
}
return true;
}
}
选择排序
从数组中找出最小的元素和数组第一个元素交换位置,然后从剩下的元素中找出最小的和数组第二个元素交换,。。。直到将整个数组排序。也就是,从未排序的部分选择最小的,和当前位置交换,始终保持左侧已排序部分有序且不再参与交换,因此内层循环不会循环到左侧已排序部分,即下面代码中始终有 j > i。
/**
* 选择排序
* 在未排序的部分找出最小的,并和当前位置交换
*/
public class Selection extends Sort {
@Override
public void sort(Comparable[] a) {
if (a == null || a.length < 2) {
return;
}
Comparable min = a[0];
for (int i = 0; i < a.length - 1; i++) {
for (int j = i + 1; j < a.length; j++) {
if (less(a[j], a[i])) {
exch(a, i, j);
}
}
}
}
}
插入排序
将当前索引位置的元素插入左侧已排序部分的合适位置,直到当前位置达到最右端。当前位置与目标位置之间的元素会被向右移动,因此内循环是从当前位置向左遍历到目标位置,始终有 j <= i。
插入排序特别适合于部分有序或近似有序的数组。
/**
* 插入排序
* 将元素插入已排序部分合适的位置
*/
public class Insertion extends Sort {
@Override
public void sort(Comparable[] a) {
if (a == null || a.length < 2) {
return;
}
for (int i = 1; i < a.length; i++) {
for (int j = i; j > 0; j--) {
if (less(a[j], a[j - 1])) {
exch(a, j, j - 1);
}
}
}
}
@Override
public void sort(Comparable[] a) {
if (a == null || a.length < 2) {
return;
}
int i, j;
for (i = 1; i < a.length; i++) {
// 方式二:将较大元素向右移动,而不是每次都交换,更快
Comparable index = a[i];
for (j = i - 1; j >= 0 && less(index, a[j]); j--) {
a[j + 1] = a[j];
}
a[j + 1] = index;
}
}
}
希尔排序
使数组中任意间隔为h的元素都是有序的(即h有序数组)。即一个h有序数组就是h个互相独立的有序数组编织在一起组成的一个数组。当h比较大时,基于插入排序,元素的移动间隔就可以很远,
/**
* 希尔排序
* 基于插入排序,移动步长为h
*/
public class Shell extends Sort {
@Override
public void sort(Comparable[] a) {
if (a == null || a.length < 2) {
return;
}
int h = 1;
while (h < a.length / 3) {
h = h * 3 + 1;
}
while (h >= 1) {
for (int i = h; i < a.length; i++) {
for (int j = i; j >= h && less(a[j], a[j - h]); j -= h) {
exch(a, j, j - h);
}
show(a);
}
h = h / 3;
}
}
}