1. 回顧
前面說到了冒泡排序,這是一種時間複雜度爲 O(n2) 、是原地排序和穩定的的排序算法,具體思路是:根據相鄰兩個元素之間比較大小,而後交換位置,得出最後排序的結果。具體可參考我寫的這一篇文章:數據結構與算法——冒泡排序,今天來看看另外兩種基礎的排序算法:選擇排序和插入排序。算法
2. 選擇排序
先來看看選擇排序,選擇排序的思路其實很簡單,將排序的數據分爲已排序區間和未排序區間,通常是以第一個元素爲已排序區間,而後依次遍歷未排序區間,找到其最小值,和未排序區間的最後一個值進行比較,交換位置。未排序區間遍歷完畢,則排序結束。光說可能有點抽象,我畫了一張圖來幫助你理解: segmentfault
是否是很簡單呢?下面是它的代碼實現:數組
public class SelectionSort { public static void selectionSort(int[] data){ int length = data.length; //若是隻有一個元素,或者數組爲空,則直接退出 if (length <= 1) return; for (int i = 0; i < length - 1; i++) { int min = i + 1; //找到最小值 for (int j = i + 1; j < length; j++) { if (data[j] < data[min]) min = j; } //交換位置 if (data[min] < data[i]){ int temp = data[min]; data[min] = data[i]; data[i] = temp; } } } }
結合代碼分析,選擇排序在最好、最壞和平均狀況下的時間複雜度都是 O(n2),而且沒有藉助額外的存儲空間,是一種原地排序算法。那麼選擇排序是穩定的嗎?答案是否認的,舉個例子:排序的數組爲 data[2, 2, 1, 3, 5, 4, 8],第一次遍歷未排序的數組,找到最小值爲 1,和第一個 2 交換位置,那麼這兩個 2 的先後順序就被打亂了,因此穩定性被破壞。正因如此,選擇排序比起冒泡排序和插入排序就顯得遜色不少了。數據結構
3. 插入排序
咱們再來看看插入排序,其實思路和上面的選擇排序很是的相似,也是將排序數據分爲已排序區間和未排序區間,依次遍歷未排序區間,和已排序區間的值進行比較,將其插入到合適的位置上,直至將未排序的區間數據遍歷完。spa
你能夠結合下面的圖來理解:3d
能夠看到,和選擇排序同樣,將第一個數據做爲已排序區間,第一次遍歷到 2 ,將其插入到 4 後面,而後再依次遍歷。
下面是代碼實現:code
public class InsertionSort { public static void insertionSort(int[] data){ int length = data.length; if (length <= 1) return; for (int i = 1; i < length; i++) { int value = data[i]; int j = i - 1; for (; j >= 0; j --){ if (data[j] > value) data[j + 1] = data[j]; else break; } data[j + 1] = value; } } }
很顯然,插入排序也是穩定的,由於咱們是在 data[j] > da[j + 1] 的時候,才進行數據交換,不會影響到相同元素的先後位置。而且,插入排序是原地排序,最好狀況下,數組原本就是有序的,因此咱們只須要遍歷一次數組就能夠了,時間複雜度是 O(n),最壞狀況和平均狀況下,時間複雜度都是 O(n2)。blog
最後還有個問題,爲何在實際中,插入排序的比冒泡排序使用的更加普遍呢?雖然這兩個排序算法的平均時間複雜度都是 O(n2),可是結合代碼,不難發現,它們涉及到的數據交換操做時略有差異的。排序
冒泡排序在交換數據的時候,須要進行三次賦值操做,而插入排序只須要一次。圖片
//插入排序的賦值操做 for (; j >= 0; j --){ if (data[j] > value) data[j + 1] = data[j]; else break; } //冒泡排序的賦值操做 for (int j = 0; j < n - i - 1; j++) { //若是data[j] > data[j + 1],交換兩個數據的位置 if (data[j] > data[j + 1]){ int temp = data[j]; data[j] = data[j + 1]; data[j + 1] = temp; }
在數據規模小的時候,這樣的差異沒什麼影響,可是若是咱們要排序的是一組較大的數據,那麼兩種排序算法的執行時間的差異就會很明顯了。