注:本文爲《算法導論》中排序相關內容的筆記。對此感興趣的讀者還望支持原作者。
基本概念
所謂插入排序,即將一個數據插入到已經排好序的有序數據中,從而得到一個新的、個數加一的有序數據,適用於少量數據的穩定排序,時間複雜度爲。既然插入排序是用於數據的排序,不如就順便闡述一下排序的概念:
輸入:n個數的一個序列.
輸出: 輸入序列的一個排列,滿足。
其中,輸出爲非降序序列。當然,在實際生活中,也可以是非升序排序,視情況而定。
算法流程
其實,插入排序的工作方式與我們日常生活中排序一手撲克牌極其相似。開始時,我們左手爲空且桌子上的牌面向下。然後,我們每次從桌子上拿走一張牌並將它插入左手中正確的位置,我們從右到左將它與已在手中的每張牌進行比較。如此,左手中的牌總是排序好的。
代碼示例
千言萬語,不如代碼一段,廢話少說,直接上代碼。此代碼段給出了簡單的插入排序的Java版本。
/**
* 插入排序的簡單實現,非降序(整型數組)
* @author 愛學習的程序員
* @version V1.0
* */
import java.util.Random;
public class InsertSort{
// 排序
public static void sort(int[] arr){
int n = arr.length;
// 數組錯誤
if(n <= 0)
return;
// 數組無需排序
else if(n ==1 )
return;
else{
int i ,j = 0;
// 中間變量,用於交換
int temp = 0;
for(i = 1; i < n; i++){
// 獲取待排序變量
temp = arr[i];
// 開始排序(由插入排序算法流程可知,此時數組a[0...i-1]已經有序)
j = i - 1;
// 逐個比較,確定待排序元素的插入位置
while(j >= 0 && temp < arr[j]){
arr[j+1] = arr[j];
j--;
}
arr[j+1] = temp;
}
}
}
public static void main(String[] args){
//測試數組生成
int[] arr = new int[10];
Random rand = new Random();
System.out.println("測試數組:");
int i = 0;
int length = arr.length;
for(i = 0; i < length; i++){
arr[i] = rand.nextInt(100);
System.out.print(arr[i]+" ");
}
// 排序
sort(arr);
// 輸出排序結果
System.out.println("\n"+"排序結果");
for(i = 0; i < length; i++)
System.out.print(arr[i]+" ");
}
}
算法分析
其實,從示例代碼中不難看出,插入排序的時間複雜度主要由確定待排序元素的插入位置以及元素的移動。因此,在最好情況下,輸入數組已排好序,則此時無需尋找待排序元素的插入位置以及移動元素。因此,在最好情況下,插入排序的時間複雜度爲O(n)。當然,“每個硬幣都有兩面”,插入排序有最好情況下,則也有最壞情況,即輸入數組方向排序。在最壞情況下,待排序元素需要和之前有序的子數組的每個元素進行比較,之後子數組內的每個元素都需要後移,則此時插入排序的時間複雜度爲。而在算法研究的大多數情況下,我們往往更加關注算法在最壞情況下的時間複雜度。
算法總結
-
優點
從上述中不難看出,插入排序思想簡單,易實現,且排序結果穩定。
-
缺點
插入排序時間複雜度爲,低效,無法用於大規模數據的排序。