排序能夠說時最基礎的算法之一,排序就是將數據按照某種邏輯從新排列的過程,好比從大到小排序、從小到大排序;排序很是常見好比有購物車物品的排序、歷史訂單的排序等等;算法咱們比較關心的主要有兩點:時間複雜度與空間複雜度,排序算法同樣;這篇文章只介紹幾種基本的排序算法:冒泡排序、插入排序、選擇排序;算法
算法邏輯上分爲已排序未排序兩個區間,從當前列表中選擇最小的元素與當前列表第一個元素交換位置,從列表剩餘元素中找到最小元素與列表第二個元素交換位置如此重複執行的算法爲選擇排序算法;
選擇排序與數據的初始狀態無關,每次查找最小元素值時都會與數組中元素進行交換位置,所以選擇排序爲非穩定排序算法,在各類狀況下算法時間複雜度都爲O(n2),空間複雜度爲O(n);數組
func SelectionSort(data [] int) { n := len(data) if n <= 1 { return } for i := 0; i < n; i++ { //最小元素索引 min := i for j := i + 1; j < n; j++ { if data[j] < data[min] { min = j } } //交換元素,交換後未已排序數據 data[i], data[min] = data[min], data[i] } }
與選擇排序相似在邏輯上列表分爲已排序和未排序兩個區間,初始時已排序區間未爲左邊第一個元素,插入排序的核心爲從右邊未排序區間中選擇元素插入到左邊合適的位置,直到已排序列表長度等於原始列表長度;插入排序算法的關鍵步驟爲元素比較與元素的移動,當從未排序端拿數據插入到已排序端時已排序端可能會存在大量的數據移動;
與選擇排序不一樣的是列表初始狀態對插入排序的性能影響很大,當列表初始狀態有序度很高時插入排序並不須要大量移動數據,從中能夠看出插入排序爲原地排序算法、算法是穩定的;
算法最好狀況下時間複雜度爲:O(n)、平均、最壞複雜度爲:O(n2);性能
func InsertionSort(data [] int) { n := len(data) for i := 1; i < n; i++ { value := data[i] //查找插入位置 var j int for j = i - 1; j >= 0; j-- { if data[j] > value { //數據後移 data[j+1] = data[j] } else { break } } data[j+1] = value } }
每次比較相鄰兩個元素是否知足,不然交換相鄰兩個元素,每次冒泡至少一個元素移動到它所屬位置,重複N次完成列表排序;
冒泡操做核心爲項鍊元素交換,空間複雜度爲O(1),爲原地排序算法;算法是穩定的,最好狀況時間複雜度爲爲O(n),平均與最壞狀況時間複雜度爲:O(n2);3d
func BubbleSort(data [] int) { n := len(data) for i := 0; i < n; i++ { //是否有數據交換,用於當某輪中數據已排序時退出循環 flag := false for j := 0; j < n-1-i; j++ { if data[j] > data[j+1] { //冒泡 data[j], data[j+1] = data[j+1], data[j] flag = true } } if !flag { break } } }
參考資料: 《算法四》code