1. Overview
Sort package implements four basic sorting algorithms: insert sort, merge sort, heap sort and quick sort. However, these four sorting methods are not public, and they are only used inside the sort package. Therefore, it is not necessary to consider which sort method should be selected when sorting data sets, as long as sort is implemented The interface defines three methods: Len() method to obtain the length of the data set, Less() method to compare the sizes of two elements, and Swap() method to exchange the positions of two elements, so that the data set can be sorted smoothly. The sort package will automatically select an efficient sorting algorithm according to the actual data. In addition, in order to facilitate the operation of common data types, the sort package provides complete support for [] int slice, [] float64 slice and [] string slice, mainly including:
- Sorting support for basic data type slices
- Basic data element lookup
- Judge whether the basic data type slices have been sorted
- Reverse the ordered data set
2. Data set sorting
As mentioned earlier, sorting data sets (including sets of user-defined data types) requires the implementation of sort For the three methods of the interface, let's look at the following definition of the interface:
type Interface interface { // Get the number of data collection elements Len() int // If the data of i index is less than the data of j index, it returns true and will not be called // The following Swap(), that is, the data is sorted in ascending order. Less(i, j int) bool // Swap the positions of the two elements of the i and j indexes Swap(i, j int) }
After the data set implements these three methods, you can call the sort () method of the package to sort. The Sort() method is defined as follows:
func Sort(data Interface)
The only parameter to the Sort() method is the data set to be sorted.
The package also provides a method to judge whether the data sets have been arranged in order. The internal implementation of this method depends on our own Len() and Less() methods:
func IsSorted(data Interface) bool { n := data.Len() for i := n - 1; i > 0; i-- { if data.Less(i, i-1) { return false } } return true }
The following is an example of sorting students' grades using the sort package:
package main import ( "fmt" "sort" ) //Student achievement structure type StuScore struct { //full name name string //achievement score int } type StuScores []StuScore //Len() func (s StuScores) Len() int { return len(s) } //Less(): grades will be sorted from low to high func (s StuScores) Less(i, j int) bool { return s[i].score < s[j].score } //Swap() func (s StuScores) Swap(i, j int) { s[i], s[j] = s[j], s[i] } func main() { stus := StuScores{ {"alan", 95}, {"hikerell", 91}, {"acmfly", 96}, {"leao", 90}} fmt.Println("Default:") //Original order for _, v := range stus { fmt.Println(v.name, ":", v.score) } fmt.Println() //StuScores has implemented sort Interface interface sort.Sort(stus) fmt.Println("Sorted:") //Ordered structure for _, v := range stus { fmt.Println(v.name, ":", v.score) } //Judge whether the order has been arranged, and true will be printed fmt.Println("IS Sorted?", sort.IsSorted(stus)) }
The custom type StuScores of the sample program implements sort Interface interface, so its object can be used as sort Sort() and sort The parameter of issorted() was passed in. Operation results:
======Default====== alan : 95 hikerell : 91 acmfly : 96 leao : 90 ======Sorted======= leao : 90 hikerell : 91 alan : 95 acmfly : 96 IS Sorted? true
This example implements ascending sorting. If you want to get descending sorting results, you just need to modify the Less() function:
//Less(): the grades are sorted in descending order. Only the less than sign is modified to the greater than sign func (s StuScores) Less(i, j int) bool { return s[i].score > s[j].score }
In addition, the sort package provides the Reverse() method, which allows the data to be sorted in reverse order according to the sorting method defined by Less(), without modifying the Less() code. The method is defined as follows:
func Reverse(data Interface) Interface
We can see a sort returned by reverse () Interface interface type. The internal implementation of Reverse() is interesting:
//Defines a reverse structure type, which is embedded in the Interface type reverse struct { Interface } //The Less() method of the reverse struct type has the opposite behavior of the embedded Less() method //The Len() and Swap() methods maintain the method behavior of the embedded type func (r reverse) Less(i, j int) bool { return r.Interface.Less(j, i) } //Returns the new data type that implements the Interface func Reverse(data Interface) Interface { return &reverse{data} }
After understanding the internal principle, you can use Reverse() in the student grade sorting example to realize the ascending sorting of grades:
sort.Sort(sort.Reverse(stus)) for _, v := range stus { fmt.Println(v.name, ":", v.score) }
The last method: Search()
func Search(n int, f func(int) bool) int
The official document describes the method as follows:
The Search() method uses the binary search algorithm to search for a specified slice [0:n], and returns the minimum i (0 < = i < n) value that can make f(i)=true. It will assume that if f(i)=true, f(i+1)=true, that is, for slice [0:n],
The slice elements before i will make the f () function return false, and the elements after i and i will make the f () function return true. However, when f(i)=true i cannot be found in the slice (at this time, none of the slice elements can make the f() function return true), the Search() method will return n.
A common way to use the Search() function is to search whether the element x is in the slice s that has been arranged in ascending order:
x := 11 s := []int{3, 6, 8, 11, 45} //Note that it has been sorted in ascending order pos := sort.Search(len(s), func(i int) bool { return s[i] >= x }) if pos < len(s) && s[pos] == x { fmt.Println(x, "stay s The location in is:", pos) } else { fmt.Println("s Contains no elements", x) }
The official document also provides a small program for guessing numbers:
func GuessingGame() { var s string fmt.Printf("Pick an integer from 0 to 100.\n") answer := sort.Search(100, func(i int) bool { fmt.Printf("Is your number <= %d? ", i) fmt.Scanf("%s", &s) return s != "" && s[0] == 'y' }) fmt.Printf("Your number is %d.\n", answer) }
3. sort package already supports internal data type sorting
As mentioned earlier, the sort package natively supports the sorting operations of three built-in data type slices of [] int, [] float64 and [] string, that is, we do not need to implement the relevant Len(), Less() and Swap () method.
1. IntSlice type and [] int sort
Since the internal implementation and usage of [] int slice sorting are similar to [] float64 and [] string, only this part is described in detail.
The sort package defines an IntSlice type and implements sort Interface:
type IntSlice []int func (p IntSlice) Len() int { return len(p) } func (p IntSlice) Less(i, j int) bool { return p[i] < p[j] } func (p IntSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } //The IntSlice type defines the sort () method and wraps the sort Sort() function func (p IntSlice) Sort() { Sort(p) } //The IntSlice type defines the SearchInts() method and wraps the SearchInts() function func (p IntSlice) Search(x int) int { return SearchInts(p, x) }
And provide sort The IntSlice type is used by the ints() method:
func Ints(a []int) { Sort(IntSlice(a)) }
Therefore, sort is more often used to sort [] int slices Ints() instead of using IntSlice type directly:
s := []int{5, 2, 6, 3, 1, 4} // Unordered slice data sort.Ints(s) fmt.Println(s) //[1 2 3 4 5 6] will be output
If you want to use descending sorting, you obviously need to use the Reverse() method mentioned earlier:
s := []int{5, 2, 6, 3, 1, 4} // Unordered slice data sort.Sort(sort.Reverse(sort.IntSlice(s))) fmt.Println(s) //[6 5 4 3 2 1] will be output
If you want to find the position of the integer x in slice a, the sort package provides SearchInts() relative to the Search() method mentioned earlier:
func SearchInts(a []int, x int) int
Note that the use condition of SearchInts() is that slice a has been sorted in ascending order
s := []int{5, 2, 6, 3, 1, 4} // Unordered slice data sort.Ints(s) //The sorted s is [1 2 3 4 5 6] fmt.Println(sort.SearchInts(s, 3)) //2 will be output
2. Float64Slice type and []float64 sorting
The implementation is similar to Ints. Just look at its internal implementation:
type Float64Slice []float64 func (p Float64Slice) Len() int { return len(p) } func (p Float64Slice) Less(i, j int) bool { return p[i] < p[j] || isNaN(p[i]) && !isNaN(p[j]) } func (p Float64Slice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } func (p Float64Slice) Sort() { Sort(p) } func (p Float64Slice) Search(x float64) int { return SearchFloat64s(p, x) }
Three methods corresponding to Sort(), IsSorted(), and Search():
func Float64s(a []float64) func Float64sAreSorted(a []float64) bool func SearchFloat64s(a []float64, x float64) int
To illustrate, in the Less method defined by the Float64Slice type above, there is an internal function isNaN(). The implementation of IsNaN () is exactly the same as that of IsNaN () in the math package. The reason why the sort package does not use math IsNaN () is completely based on package dependency. It should be noted that the implementation of sort package does not depend on any other package.
3. StringSlice type and [] string sorting
The size comparison between two string objects is based on "dictionary order".
The implementation is similar to Ints. Just look at its internal implementation:
type StringSlice []string func (p StringSlice) Len() int { return len(p) } func (p StringSlice) Less(i, j int) bool { return p[i] < p[j] } func (p StringSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } func (p StringSlice) Sort() { Sort(p) } func (p StringSlice) Search(x string) int { return SearchStrings(p, x) }
Three methods corresponding to Sort(), IsSorted(), and Search():
func Strings(a []string) func StringsAreSorted(a []string) bool func SearchStrings(a []string, x string) int
Transferred from: https://blog.csdn.net/gongpulin/article/details/80843921