在個人筆記裏面找到幾種經常使用的排序代碼,包括「冒泡排序、選擇排序、二分排序、快速排序」。關於這些排序的原理,我以前是有專門研究的,網上也有不少教程。算法
package main import ( "fmt" "math/rand" "time" ) func main() { rand.Seed(time.Now().Unix()) s := randInt(20) BubblingSort(s, len(s)) fmt.Println(s) s = randInt(20) SelectSort(s, len(s)) fmt.Println(s) s = randInt(20) BisectionSort(s, len(s)) fmt.Println(s) s = randInt(20) quickSort(s, 0, len(s)-1) fmt.Println(s) } func randInt(n int) []int { res := make([]int, n) for i := 0; i < n; i++ { res[i] = rand.Intn(100) } return res } func BubblingSort(nums []int, ln int) { for i := 0; i < ln-1; i++ { flag := true for j := 0; j < ln-i-1; j++ { if nums[j] > nums[j+1] { nums[j], nums[j+1] = nums[j+1], nums[j] flag = false } } if flag { break // 已經有序,不用繼續 } } } func SelectSort(nums []int, ln int) { for i := 0; i < ln; i++ { min := i for j := i + 1; j < ln; j++ { if nums[min] > nums[j] { min = j } } nums[i], nums[min] = nums[min], nums[i] } } func BisectionSort(nums []int, ln int) { for i := 1; i < ln; i++ { tmp := nums[i] low, mid, high := 0, -1, i-1 for low <= high { mid = (low + high) / 2 if tmp < nums[mid] { high = mid - 1 } else { low = mid + 1 } } for j := i - 1; j >= low; j-- { nums[j+1] = nums[j] } if low != i { nums[low] = tmp } } } func quickSort(num []int, low, high int) { s, e, k := low, high, num[low] for e > s { for e > s && num[e] >= k { e-- } if num[e] <= k { num[s], num[e] = num[e], num[s] } for e > s && num[s] <= k { s++ } if num[s] >= k { num[s], num[e] = num[e], num[s] } if s > low { quickSort(num, low, s-1) } if e < high { quickSort(num, e+1, high) } } }
package main import ( "fmt" "math/rand" "sort" "time" ) func main() { rand.Seed(time.Now().Unix()) s := randInt(20) sort.Ints(s) fmt.Println(s) } func randInt(n int) []int { res := make([]int, n) for i := 0; i < n; i++ { res[i] = rand.Intn(100) } return res }
package main import ( "fmt" "math/rand" "sort" "time" ) func main() { rand.Seed(time.Now().Unix()) s := randFloat64(20) sort.Float64s(s) fmt.Println(s) } func randFloat64(n int) []float64 { res := make([]float64, n) for i := 0; i < n; i++ { res[i] = rand.Float64() } return res }
package main import ( "encoding/base64" "fmt" "math/rand" "sort" "time" ) func main() { rand.Seed(time.Now().Unix()) s := randString(20) sort.Strings(s) fmt.Println(s) } func randString(n int) []string { res := make([]string, n) tmp := make([]byte, 10) for i := 0; i < n; i++ { rand.Read(tmp) res[i] = base64.StdEncoding.EncodeToString(tmp) } return res }
對於自定義類型,須要實現Less
、Swap
、Len
這三個sort包的接口,而後直接使用sort.Sort
方法就能夠了。less
package main import ( "encoding/base64" "fmt" "math/rand" "sort" ) func main() { peoples := SortPeople{ { name: "張三", age: 25, }, { name: "李四", age: 18, }, { name: "王五", age: 20, }, } sort.Sort(peoples) fmt.Println(peoples) } type ( people struct { name string age int } SortPeople []people ) func (d SortPeople) Less(i, j int) bool { return d[i].age < d[j].age } func (d SortPeople) Swap(i, j int) { d[i], d[j] = d[j], d[i] } func (d SortPeople) Len() int { return len(d) }
直接使用sort.Slice只須要定義less func(i, j int) bool
方法就能夠完成排序,代碼是經過快速排序完成,不過具體實現加了反射,性能稍微有影響。性能
package main import ( "encoding/base64" "fmt" "math/rand" "sort" ) func main() { peoples := []people{ { name: "張三", age: 25, }, { name: "李四", age: 18, }, { name: "王五", age: 20, }, } sort.Slice(peoples, func(i, j int) bool { return peoples[i].age < peoples[j].age }) fmt.Println(peoples) }
該方法相似上一個方法,我看具體實現是使用一個穩定的排序算法。ui
package main import ( "encoding/base64" "fmt" "math/rand" "sort" ) func main() { peoples := []people{ { name: "張三", age: 25, }, { name: "李四", age: 18, }, { name: "王五", age: 20, }, } sort.SliceStable(peoples, func(i, j int) bool { return peoples[i].age < peoples[j].age }) fmt.Println(peoples) }
排序算法是算法的基礎,理解算法具體實現有利於鍛鍊思惟,以及經過分析排序的優缺點,在合適的時候使用合適的排序方法。最重要的是高效和節省資源的平衡,經過研究go自帶的排序包,發現官方排序會根據數據量將排序分紅不一樣的方式進行,不過最重要的仍是快速排序。code