开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第26天,点击查看活动详情
插入排序
插入排序也被称为直接插入排序。
插入排序是将一个元素插入到已经排好序的数组或有序表中,从而生成一个新的数组或有序表。
排序原理
假如数组长度为N,使用插入排序对其进行排序,先从最左边开始,先让0 ~ 0范围有序这不废话,再让0 ~ 1范围有序,再让0 ~ 2范围有序,以此类推,直到0 ~ N范围上有序。
给定一组数据:
3, 5, 2, 7, 1, 8, 13, 9, 12
第1次,让0 ~ 0范围有序,即一个数字3肯定是有序的,直接跳过。
第2次,让0 ~ 1范围有序,3, 5也是有序的,直接跳过。
第3次,让0 ~ 2范围有序,2比5小,让2和5进行交换,继续向左,2比3小,让2和3进行交换,排序结果为2, 3, 5, 7, 1, 8, 13, 9, 12。
第4次,让0 ~ 3范围有序,2, 3, 5, 7是有序的直接跳过。
第5次,让0 ~ 4范围有序,1比7小,1和7进行交换,1比5小,1和5进行交换,1比3小,1和3进行交换,1比2小,1和2进行交换,排序结果为1, 2, 3, 5, 7, 8, 13, 9, 12。
以此类推,直到所有数据都排好序。
代码实现
public class Code05_InsertionSort {
public static void main(String[] args) {
int[] arr = {3, 5, 2, 7, 1, 8, 13, 9, 12};
print(arr);
insertionSort(arr);
print(arr);
}
public static void insertionSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
for (int i = 1; i < arr.length; i++) {
int j = i;
while (j - 1 >= 0 && arr[j - 1] > arr[j]) {
swap(arr, j - 1, j);
j--;
}
}
}
public static void swap(int[] arr, int i, int j) {
arr[i] = arr[i] ^ arr[j];
arr[j] = arr[i] ^ arr[j];
arr[i] = arr[i] ^ arr[j];
}
public static void print(int[] arr) {
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
}
运行输出结果为:
3 5 2 7 1 8 13 9 12
1 2 3 5 7 8 9 12 13
优化代码实现
代码嘛,也不是说越长越好,当然短的代码也不一定就是好的。上面这个代码能不能再端一点呢?while这一段代码看起来挺啰嗦的,下面就对while这里做一点小小的优化。
public static void insertionSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
for (int i = 1; i < arr.length; i++) {
for (int j = i - 1; j >= 0 && arr[j] > arr[j + 1]; j--) {
swap(arr, j, j + 1);
}
}
}
希尔排序
希尔排序也是一种插入排序算法,比简单插入排序更高效,也称为缩小增量排序。
排序原理
将一个无序数组分割几个子数组,每个子数组间隔相同的增量(一般的第一个增量为数组长度的一半),对各个子数组进行插入排序;接着再缩小增量(一般的第二个增量为第一个增量的一半),分割成新的子数组进行插入排序,最后增量缩减为1,对所有元素进行最后一次插入排序。
给定一组数据:
3, 5, 2, 7, 1, 8, 13, 9, 12
数组长度为9,初始增量gap=9/2=4,把整个数组分为4组,[3,1],[5,8],[2,13],[7,9,12]。
对这4组分别进行直接插入排序,排序结果为1, 5, 2, 7, 3, 8, 13, 9, 12,可以看到,小值元素都被调到前面去了,然后缩小增量,gap=4/2=2,数组被分为2组,[1,2,3,13],[5,7,8,9,12]。
对这2组再分别进行直接插入排序,排序结果为1, 5, 2, 7, 3, 8, 12, 9, 13,可以看到离有序更近一步了,再缩小增量gap=2/2=1,整个数组被分为1组。
此时,对数组再做简单的调整即可。
代码实现
public class Code06_ShellSort {
public static void main(String[] args) {
int[] arr = {3, 5, 2, 7, 1, 8, 13, 9, 12};
print(arr);
shellSort(arr);
print(arr);
}
public static void shellSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
int N = arr.length;
for (int gap = N / 2; gap > 0; gap /= 2) {
for (int i = gap; i < N; i++) {
int j = i;
while (j - gap >= 0 && arr[j] < arr[j - gap]) {
swap(arr, j, j - gap);
j -= gap;
}
}
}
}
public static void swap(int[] arr, int i, int j) {
arr[i] = arr[i] ^ arr[j];
arr[j] = arr[i] ^ arr[j];
arr[i] = arr[i] ^ arr[j];
}
public static void print(int[] arr) {
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
}
运行输出结果为:
3 5 2 7 1 8 13 9 12
1 2 3 5 7 8 9 12 13