前言
在玩撲克牌的時候,我們抽到一張牌的時候,都是將它插入到當前手中牌的合適位置的。
如下圖:
(上圖來自算法導論)
直接插入排序也是這樣的思想。
基本思想
插入排序的思想是:
將待排序序列分成兩個序列,前面的序列保持有序,依次選取后面的序列的元素,在前面的序列中進行插入。
初始時,有序序列的長度為1。
例子
給定序列
[9 , 20 , 13 , 20 , 12 ] 。
初始狀態如下:
分成兩個序列如下:
定義兩個變量 val 和 index。其中val表示后面序列中待插入的元素,index表示前面序列中插入的索引。
第一次插入
將 val初始化為 arr[1],即20;
將Index初始化為當前val值的前一個元素的索引,即0;
此時 arr[index] < val 不用移動,index-- 后將變為負數,退出循環。
第一次插入結束。
變成如下狀態:
第二次插入
將 val初始化為 arr[2],即10;
將Index初始化為當前val值的前一個元素的索引,即1;
此時 arr[index] > val 並不是合適的插入位置,將index代表的元素向后移動;
index--;
此時 arr[index] < val 找到了插入位置,即 index + 1;
退出當前循環;
將 arr[index+1] 賦值為val;
得到如下狀態圖:
第三次插入
將 val初始化為 arr[3],即13;
將Index初始化為當前val值的前一個元素的索引,即2;
此時 arr[index] > val 並不是合適的插入位置,將index代表的元素向后移動;
得到如下狀態圖:
index--;
此時 arr[index] < val 找到了插入位置,即 index + 1;
退出當前循環;
將 arr[index+1] 賦值為val;
得到如下狀態圖:
第四趟插入
代碼
先定義變量;
int value;//待插入元素
int index;//初始值為待插入元素前一個元素的索引
由算法思想和例子解釋,寫成最終代碼如下:
import java.lang.reflect.Array;
import java.util.Arrays;
public class Solution {
public static void main(String[] args) {
InsertSort(new int[] { 9 ,20 , 10, 13 , 12});
}
public static void InsertSort(int [] arr){
int value;//待插入元素
int index;//初始值為待插入元素前一個元素的索引
for(int i= 1 ; i< arr.length;i++){
//i從第二個元素開始,默認第一個元素是有序的
//循環條件是小於數組長度,因為也要將最后一個元素插入到前面的序列
value = arr[i];
index = i - 1;//初始為前一個元素
while(index >=0 && value < arr[index]){
//需要保證index合法
//每當前面的元素比待插入元素大,就向后移動
arr[index + 1] = arr[index];
//不用怕覆蓋,因為value保存着待插入的值
index--;
}
//當退出循環,表明已經找到了待插入位置,即index + 1
arr[index + 1] = value;
}
System.out.println(Arrays.toString(arr));
}
}
時間復雜度
在排序前元素已經是按需求有序了,每趟只需與前面的有序元素序列的最后一個元素進行比較,總的排序碼比較次數為n-1,元素移動次數為0。時間復雜度為$O(n)$;
而在最差的情況下,及第i趟時第i個元素必須與前面i個元素都做排序碼的比較,並且每做一次就叫就要做一次數據移動,此時的時間復雜度為 $O(n^2)$;
所以直接插入排序的時間復雜度為$O(n^2)$。
穩定性
插入排序是在一個已經有序的小序列的基礎上,一次插入一個元素。如果碰見一個和插入元素相等的,那么將會把待插入元素放在相等元素的后面。所以,相等元素的相對的前后順序沒有改變,所以插入排序是穩定的。
歡迎關注
歡迎大家的關注
掃描下方的二維碼或者微信搜一搜即可關注我的微信公眾號:code隨筆