1. 选择排序
将第i小的元素放在第i个位置
// 选择排序,将第i小的元素放在a[i]上
public static void selectionSort(Comparable[] a) {
for (int i = 0; i < a.length; i++) {
int min = i;
for (int j = i + 1; j < a.length; j++)
if (less(a[j], a[min]))
min = j;
if (min == i)// 如果自己就是最小的则不用交换,跳过
continue;
exchange(a, min, i);
}
}
大约需要n²/2次比较
,n²/2次交换
选择排序时间主要花费在比较
上,我后面使用了一个判断语句
避免了不必要的交换
2. 插入排序
将一个新元素插入到已经排好序的数组中
主要是消除逆序组合
更加适用于部分有序数组
// 插入排序,将一个新的元素插入到已经排好序的数组中,边比较边交换
public static void insertionSort(Integer[] a) {
for (int i = 1; i < a.length; i++)
for (int j = i; j >= 1 && less(a[j], a[j - 1]); j--)// 将比较放在条件里可以减少比较次数
exchange(a, j, j - 1);// 交换相邻的2个元素
}
// 将较大的元素直接后移,腾出一个位置
public static void insertionSort1(Integer[] a) {
for (int i = 1; i < a.length; i++) {
int j = i;
Integer temp = a[j];// 保存当前元素
while (j > 0 && less(temp, a[j - 1])) {
a[j] = a[j - 1];// 元素后移
j--;
}
a[j] = temp;
}
}
具体有2种实现方法:
- 一直
交换
- 一直
后移元素
,找到位置后直接插入
对于第1种方法:
情况 | 比较次数 | 交换次数 |
---|---|---|
平均情况 | n²/4 | n²/4 |
最坏情况 | n²/2 | n²/2 |
最好情况 | n-1 | 0 |
最后通过代码验证,第2种方法效率更高
3. 希尔排序
是一种插入排序的变体,仅仅增加了几行代码,效率大大提升
插入排序只能一次移动一个距离,而希尔排序可以移动很远的距离
希尔排序的思想:使数组任意间隔为h的元素都是有序的
分成了多个插入排序的过程,依次王每个数组中插入新元素,最后一次总是1-sorted.
h递增序列
的选择很重要,一般选择3 * h + 1(兼顾奇偶)
// 希尔排序,基于插入排序的快速排序算法,不断地使部分有序,消除逆序数
public static void shellSort(Comparable[] a) {
int h = 1;
while (h < a.length / 3)
h = 3 * h + 1;// 递增序列: 1, 4, 13, 40······
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)// 因为是向前遍历,所以这里的条件是>=h,不然-h就会下标越界
exchange(a, j, j - h);
h /= 3;// 不断地缩小局部间隔
}
}
// 使用选择排序的希尔排序
public static void shellSort1(Integer[] a) {
int h = 1;
while (h < a.length / 3)
h = 3 * h + 1;
while (h >= 1) {
for (int i = 0; i < a.length - h; i++) {
int min = i;
for (int j = i + h; j < a.length; j += h)
if (less(a[j], a[min]))
min = j;
if (min == i)// 如果自己就是最小的则不用交换,跳过
continue;
show(a, min, i);
exchange(a, min, i);
}
h /= 3;
}
show(a, -1, -1);
}
最后,上2个辅助方法:
// 将对象数组a中的i1,i2个对象交换位置
public static void exchange(Comparable[] a, int i1, int i2) {
Comparable temp = a[i1];
a[i1] = a[i2];
a[i2] = temp;
}
// a是否小于b
public static boolean less(Comparable a, Comparable b) {
return a.compareTo(b) < 0;
}