直接插入排序
将待排序序列分为有序区和无序区,将无序区的元素逐一插入到有序区合适的位置上,直到全部有序。
类似玩牌时整理排的过程。
直接插入排序步骤
1.以数组第一个元素为有序区。
2.将无序区的第一个元素关键码,插入到有序区。
- 寻找关键码在有序区的目标位置
- 插入关键码
重复步骤2,直至全部有序。
直接插入排序演示:
算法分析
直接插入排序-java实现
/**
* 直接插入排序的分步理解
*
* @param arr
*/
public static void straightInsertionSort_step(int[] arr) {
int size = arr.length;
for (int i = 1; i < size; i++) { // arr[i]为关键码
int destIndex = 0; // 插入的目标下标
int key = arr[i]; // 保存关键码
// 遍历寻找destIndex
for (int j = i - 1; j >= 0; j--) {
if (arr[j] <= key) { // 如果关键码>=序区元素j,则插入j之后,否则,插入0下标
destIndex = j + 1;
break;
}
}
// 后移记录
for (int j = i - 1; j >= destIndex; j--) {// 从前向后会覆盖
arr[j + 1] = arr[j];
}
// 插入
arr[destIndex] = key;
System.out.print("第 " + i + "轮 :" + Arrays.toString(arr));
System.out.println(" destIndex:" + destIndex);
}
}
/**
* 直接插入排序
*
* @param arr
*/
public static void straightInsertionSort(int[] arr) {
int size = arr.length;
for (int i = 1; i < size; i++) { // 外层控制轮数
int key = arr[i]; // arr[i]为关键码
int j = i - 1;
for (; j >= 0 && key < arr[j]; j--){ //如果关键码>=序区元素j,则插入j之
arr[j + 1] = arr[j]; // 在寻找关键码插入位置的同时将元素后移
}
arr[j + 1] = key; // 插入目标位置
System.out.print("第 " + i + "轮 :" + Arrays.toString(arr));
System.out.println(" destIndex:" + (j + 1));
}
}
希尔排序
希尔排序是对直接插入排序的一种改进,着眼于:
- 若排序记录按关键码基本有序,直接插入排序的效率很高;
- 记录个数少,直接插入排序效率高。因为直接插入排序时间复杂度为O(n^2),n越小,效率越高。
希尔排序思想:
- 把记录按步长 gap 分组,对每组记录采用直接插入排序方法进行排序。保证整个序列基本有序。
- 随着步长逐渐减小,所分成的序列包含的记录越来越多,当步长的值减小到 1 时,所有记录合成为一组,经过直接插入排序后,构成一组有序记录,则完成排序。
开始时增量的取值较大,每个子序列记录个数少,排序效率较高;后来增量逐步缩小,每个子序列中的记录个数增加,但已经基本有序,故排序效率也较高。
希尔排序演示:
算法分析
希尔排序-java实现
/**
* “把记录按步长 gap分组,对每组记录采用直接插入排序方法进行排序。保证整个序列基本有序.”<br>
* @param arr
*/
public static void shellSort(int[] arr) {
int size = arr.length;
//把下标增量为gap的记录编为一个子序列
//增量逐步减小,直到整个序列的子序列为本身,即增量gap=1
for (int gap = size / 2; gap >= 1; gap /= 2) {
//对子序列进行直接插入排序
for (int i = gap; i < size; i++) {
int key = arr[i];
int j = i - gap;
for (; j >= 0 && key < arr[j]; j -= gap) {
arr[j + gap] = arr[j];
}
arr[j + gap] = key;
}
System.out.println("gap: " + gap + " :" + Arrays.toString(arr));
}
}



