在个人笔记里面找到几种经常使用的排序代码,包括“冒泡排序、选择排序、二分排序、快速排序”。关于这些排序的原理,我以前是有专门研究的,网上也有不少教程。算法
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