#簡單演算法知識--插入排序
1.1.1插入排序的原理 通過上面的原理圖我們可以看出,直接插入排序的基本操作是將一個記錄插入到已經排好的有序表中,從而得到一個新的、記錄數增1的有序表。對於給定的一組記錄,初始時假定第一個記錄自成一個有序序列,其餘記錄為無序序列。接著從第二個記錄開始,按照記錄的大小依次將當前處理的記錄插入到其之前的有序序列中,直到最後一個記錄插到有序序列中為止。因此,在上圖中,插入排序實際上完成插入的輪數為n-1(n為數的個數),從第二行開始進行插入操作,我們可以描述一下這個過程: 在第二輪資料中,通過插入24來組成新的有序陣列:[-23,24]; 在第三輪資料中,通過在有序陣列[-23,24]插入12來組成新的有序陣列[-23,12,24]; 在第三輪資料中,通過在有序陣列[-23,24]插入12來組成新的有序陣列[-23,12,24]; 以此類推。實際上,插入排序是通過生活中的例子總結而來的,比較熟悉是玩撲克牌,插入排序類似於將抓到的撲克牌插入到現有的撲克牌中,現有的撲克牌是已經排好順序的,我們從桌子上的牌堆中(按順序抓下一張牌,而不是隨機抓牌)抓牌就好比從原陣列中獲取陣列的緊接著的那一個數字,然後將這張撲克牌插入到左手現有排好順序的撲克牌中,插排的這個過程就好比從原陣列中獲取陣列的緊接著的那一個數字,並將這個數字插入到現有排好的那一個數組中。 演算法分析: 第一輪插入:從原陣列取出第二個數arr[1]執行插入,插入的位置取決於第一個數arr[0]的大小,因此這個過程可表示為: if arr[1] < arr[0] int temp = arr[1]; arr[1] = arr[0];//將原陣列的第一個數向右移動一個位置 arr[0] = temp; 這個過程可表示為:
while(i>=0 && temp < arr[i]){//注意這裡temp不能寫成arr[i+1],因為arr[i+1]是動態變化的,而比較插入資料與其他資料的大小時,插入資料是需要保持不變的,因此需要使用一個temp將這個插入資料儲存起來,然後再進行比較。 //將原陣列的第i+1個數(arr[i])向右移動一個位置 arr[i+1] = arr[i]; i–; } //最終是想將迴圈後的arr[i]與int temp中的arr[i+1]進行替換,但是i=i-1了,因此還需+1(i大於=0是控制元素的下標) arr[i+1] = temp;
因此,最終插入排序的程式碼如下所示: package com.yzh.maven.main; public class InsertSort { public static void main(String[] args) { int[] arr = new int[]{-34,23,5,78,0,-45,90,12,-88,34}; //需要進行n-1輪資料的插入排序 for(int i = 1;i<arr.length;i++){ int j = i-1; //從第一輪的第二個數開始做插入排序 int insertNum = arr[j+1]; while(j>=0 && insertNum<arr[j]){ //將原陣列的第i+1個數(arr[i])向右移動一個位置 arr[j+1] = arr[j]; //繼續往前推移 j–; } //把插入的資料放在合適的位置 arr[j+1] = insertNum; } } } 對於插入排序的時間複雜度如下所示。 最差情況:反序,需要移動n*(n-1)/2個元素 最好情況:正序,不需要移動元素 陣列在已排序或者是“近似排序”時,插入排序效率的最好情況執行時間為O(n); 插入排序最壞情況執行時間和平均情況執行時間都為O(n2)。 因此,一般情況下,插入排序的效率大於選擇排序大於氣泡排序。