基本思想
首先,我們將數組中的數據分為已排序區間和未排序區間,初始已排序區間只有一個元素,就是數組的第一個元素。插入算法的核心思想是取未排序區間中的元素,在已排序區間中找到合適的插入位置將其插入,并保證已排序區間數據一直有序。重復這個過程,直到未排序區間中元素為空,算法結束。
兩種操作:比較和移動
代碼示例
/**
處理流程: 設數組為a[0…n-1]。
1. 初始時,a[0]自成1個有序區,無序區為a[1..n-1]。令i=1
2.將a[i]并入當前的有序區a[0…i-1]中形成a[0…i]的有序區間。
3. i++并重復第二步直到i==n-1。排序完成。
* 直接選擇排序與直接插入排序對比理解: 直接選擇排序和直接插入排序類似,都將數據分為有序區和無序區,
* 所不同的是直接插入排序是將無序區的第一個元素直接插入到有序區以形成一個更大的有序區,
* 而直接選擇排序是從無序區選一個最小的元素直接放到有序區的最后。
*
* @author yeoggc
*
*/
public class 直接插入排序 {
// 打印序列
public void printPart(int[] list, int begin, int end) {
for (int i = 0; i < begin; i++) {
System.out.print("\t");
}
for (int i = begin; i <= end; i++) {
System.out.print(list[i] + "\t");
}
System.out.println();
}
public static void main(String[] args) {
// 初始化一個隨機序列
// final int MAX_SIZE = 10;
// int[] array = new int[MAX_SIZE];
// Random random = new Random();
// for (int i = 0; i < MAX_SIZE; i++) {
// array[i] = random.nextInt(MAX_SIZE);
// }
// 初始化一個固定值序列
int[] array = { 0, 6, 7, 4, 4, 1, 0, 6, 2, 3 };
直接插入排序 insert = new 直接插入排序();
System.out.print("排序前:\t");
insert.printPart(array, 0, array.length - 1);
insert.insertSort(array);
System.out.print("排序后:\t");
insert.printPart(array, 0, array.length - 1);
}
private void insertSort(int[] array) {
// 第1個數肯定是有序的,從第2個數開始遍歷,依次插入有序序列
// i表示待排序元素在數組的下標
for (int i = 1; i < array.length; i++) {
int temp = array[i];// 待排序的數據
int j = 0;// 有序區中待排序元素的下標,初始時,從有序區最后一個元素開始比較起
// 因為前i-1個數都是從小到大的有序序列,所以只要當前比較的數(list[j])比temp大,就把這個數后移一位
for (j = i - 1; j >= 0 && array[j] > temp; j--) {
array[j + 1] = array[j];
}
array[j + 1] = temp;// 把待排序的元素值放入合適的位置
System.out.format("i = %d:\t", i);
printPart(array, 0, i);
}
}
}
算法分析
直接插入排序是穩定的排序。
關于各種算法的穩定性分析可以參考
文件初態不同時,直接插入排序所耗費的時間有很大差異。若文件初態為正序,則每個待插入的記錄只需要比較一次就能夠找到合適的位置插入,故算法的時間復雜度為O(n),這時最好的情況。若初態為反序,則第i個待插入記錄需要比較i+1次才能找到合適位置插入,故時間復雜度為O(n2),這時最壞的情況。
直接插入排序的平均時間復雜度為O(n2)。