Go language Sort and search

Source: Internet
Author: User
Tags sorts

When you are ready to write a go program in the evening, think about how go is sorted. Sorting sort is a basic operation, of course searching for search too. C provides a qsort and bsearch, a quick binary search, but not easy to use; the sort in C + + looks pretty good because C + + supports generics (or templates), so a lot of things are handy to use. Go is a sort package to provide sorting and search, because go temporarily does not support generics (in the future is not supported), so the go sort and search used with the type is related, or need to write as c as the comparison function, a little less convenient.


Note: Recently looked at the sort of go, found that the previous sort of go to understand a bit shallow. Go's sort ideas are somewhat different from C and C + +. C is sorted by default for arrays, C + + is a sequence of sorts, go is more broad, to be sorted can be any object, although in many cases is a slice (shard, similar to an array), or contains an object slice.


Three elements of a sort (interface):


Number of elements to be sorted n;
The comparison function CMP of the first and the J elements;
Swap swap for elements I and J;
At first glance, condition 3 is redundant, and C and C + + do not provide swap. Qsort usage of C: qsort (data, n, sizeof (int), cmp_int); Data is the starting address, N is the number of elements, and sizeof (int) is the size of each element, and Cmp_int is a function that compares two int. The use of the sort in C + +: Sort (data, data+n, cmp_int); Data is the position of the first element, Data+n is the next position of the last element, and Cmp_int is the comparison function.


The following is still the point of entry.


Ordering of primitive types int, float64, and string
Sort Ascending
For the ordering of int, float64, and string arrays or shards, go provides a sort. Ints (), sort. Float64s () and sort. The Strings () function, by default, is ordered from small to large. (No sort.) Float32s () function, me quite a bit strange. )


Package Main

Import (
"FMT"
"Sort"
)

Func Main () {
Intlist: = [] int {2, 4, 3, 5, 7, 6, 9, 8, 1, 0}
Float8list: = [] float64 {4.2, 5.9, 12.3, 10.0, 50.4, 99.9, 31.4, 27.81828, 3.14}
Float4list: = [] float32 {4.2, 5.9, 12.3, 10.0, 50.4, 99.9, 31.4, 27.81828, 3.14}//No function:sort. Float32s
Stringlist: = [] string {"A", "C", "B", "D", "F", "I", "Z", "X", "W", "Y"}

Sort. Ints (Intlist)
Sort. float64s (Float8list)
Sort. Strings (Stringlist)

Fmt. Printf ("%v\n%v\n%v\n", Intlist, Float8list, Stringlist)

}
Sort Descending
int, float64, and string have the default ascending sort function, and now the question is, what if descending? People with other language programming experience know that just swapping CMP's rules of comparison is possible, and the implementation of GO is similar, but different. You can use sort to sort the object obj for a Type in go. Sort (obj), which requires three methods to be bound to type types: Len () for length, less (I,J) to compare the functions of the size of the first and the J elements, swap (I,J) for the functions of the first and the J elements. The three types under the sort package intslice, Float64slice, and Stringslice implement the three methods respectively, corresponding to the [] int, [] float64, and [] string. If you want to sort in reverse order, simply modify the less function.


The Go Sort pack can use sort. Reverse (slice) to exchange slice. Interface.less, which is the comparison function, so the inverse sort function of int, float64, and string can be written like this:


Package Main

Import (
"FMT"
"Sort"
)

Func Main () {
Intlist: = [] int {2, 4, 3, 5, 7, 6, 9, 8, 1, 0}
Float8list: = [] float64 {4.2, 5.9, 12.3, 10.0, 50.4, 99.9, 31.4, 27.81828, 3.14}
Stringlist: = [] string {"A", "C", "B", "D", "F", "I", "Z", "X", "W", "Y"}

Sort. Sort (sort. Reverse (sort. Intslice (intlist)))
Sort. Sort (sort. Reverse (sort. Float64slice (float8list)))
Sort. Sort (sort. Reverse (sort. Stringslice (stringlist)))

Fmt. Printf ("%v\n%v\n%v\n", Intlist, Float8list, Stringlist)
}
In-depth understanding of sorting
There is a sort in the sort package. The Interface interface has three methods Len (), Less (I,J), and Swap (I,J). General sorting function Sort. Sort can be sorted by any implementation of sort. The object (variable) of the Inferface interface. for [] int, [] float64, and [] string in addition to using specially specified functions, you can also use modified types Intsclice, Float64slice, and Stringslice, and then directly invoke their corresponding Sort () method; Because these three types also implement the sort. Interface interface, so you can pass the sort. Reverse to convert these three types of interface.less methods to achieve reverse ordering, which is the use of the last sort before.


The following uses a custom (user-defined) Reverse struct instead of sort. Reverse function to implement reverse ordering.


Package Main

Import (
"FMT"
"Sort"
)

Custom type of Reverse
Type Reverse struct {
Sort. Interface//In this way, Reverse can accept any implementation of the sort. Interface objects (including Len, less, Swap three methods)
}

Reverse just reversed the order of the inferface.less.
Func (R Reverse) Less (i, J int) bool {
Return R.interface.less (J, i)
}

Func Main () {
INTs: = []int{5, 2, 6, 3, 1, 4}//unsorted

Sort. Ints (Ints)//Special sort function, ascending
Fmt. Println ("After sort by ints:\t", Ints)//[1 2 3 4 5 6]

Doubles: = []float64{2.3, 3.2, 6.7, 10.9, 5.4, 1.8}

Sort. float64s (Doubles)//float64 sort version 1
Fmt. Println ("After sort by float64s:\t", doubles)//[1.8 2.3 3.2 5.4 6.7 10.9]

Strings: = []string{"Hello", "good", "students", "Morning", "people", "World"}
Sort. Strings (Strings)
Fmt. Println ("After sort by strings:\t", Strings)//[Good Hello Mornig people students World]

IPOs: = sort. Searchints (INTs,-1)//int Search
Fmt. Printf ("Pos of 5 is%d th\n", IPOs)///not always correct! (Search is not the point)

Dpos: = sort. searchfloat64s (doubles, 20.1)//Float64 Search
Fmt. Printf ("Pos of 5.0 is%d th\n", dpos)///not always correct!

Fmt. Printf ("Doubles is ASC?") %v\n ", sort. float64saresorted (doubles))

Doubles = []float64{3.5, 4.2, 8.9, 100.98, 20.14, 79.32}
Sort. Sort (sort. Float64slice (Doubles))//Float64 sorting Method 2
Fmt. Println ("After sort by sort:\t", doubles)//[3.5 4.2 8.9 20.14 79.32 100.98]
(Sort. Float64slice (doubles)). Sort ()//Float64 sorting Method 3
Fmt. Println ("After sort by sort:\t", doubles)//[3.5 4.2 8.9 20.14 79.32 100.98]

Sort. Sort (Reverse{sort. Float64slice (Doubles)})//float64 reverse order
Fmt. Println ("After sort by reversed sort:\t", doubles)//[100.98 79.32 20.14 8.9 4.2 3.5]
}
Sort. Ints/sort. Float64s/sort. Strings the integer/floating-point/string-type shards, or fragments, or not strictly arrays, to sort. Then there is a function that tests whether it is ordered. There are also corresponding search functions, however, it is found that the search function can only be positioned if there is no location, the position is not correct.


About the general array sorting, the program shows that there are 3 ways! Currently available three types of Int,float64 and string are symmetric, that is, you have, corresponding to me also have.


About flipping or reversing the order, you can rewrite the less function with a flip structure. The Reverse above is a general-purpose structure.


It says so much, just sort the basic types, it's time to talk about the sort of struct structure type, and actually this will be more.


sort of struct type
The structure type is sorted by using sort. Sort (slice) is implemented as long as the slice implements the sort. There are three ways to Interface. That said, there are several ways to sort it out. The first is to simulate a sort [] int to construct the corresponding Intslice type, and then implement the Interface three methods for the Intslice type.


Structure Sorting Method 1
Package Main

Import (
"FMT"
"Sort"
)

Type person struct {
Name string//Name
Age int//Old
}

Sort by person.age from big to small
Type Personslice [] person

Func (a personslice) len () int {//override Len () method
Return Len (a)
}
Func (a personslice) swap (i, J int) {//override Swap () method
A[i], a[j] = A[j], a[i]
}
Func (a personslice) less (i, J int) bool {//rewrite lesser () method, sort from large to small
Return A[J]. Age < A[i]. Age
}

Func Main () {
People: = [] person{
{"Zhang San", 12},
{"Li si", 30},
{"Wang Wu", 52},
{"Zhao Liu", 26},
}

Fmt. Println (People)

Sort. Sort (Personslice (people))//Sort by the reverse order of age
Fmt. Println (People)

Sort. Sort (sort. Reverse (Personslice (people))//Sort in ascending order of age
Fmt. Println (People)

}
This is completely a simulation of the way, so if you understand intslice nature understand here, in turn, understand here so intslice there also understand.


Structure Sorting Method 2
The disadvantage of Method 1 is that you need to redefine the Personslice method according to the age ordering, bind the Len, less, and Swap methods, and if you need to sort by Name, you need to write three more functions, and if the struct has 4 fields and four types of sorting, then Write 3x4 = 12 methods, even if some are completely superfluous, o__o "... Think carefully, depending on the standard age or Name, the real difference is in the less method, so the Me abstracts the less, and each sort of less makes it dynamic, such as the following method.


Package Main

Import (
"FMT"
"Sort"
)

Type person struct {
Name string//Name
Age int//Old
}

Type Personwrapper struct {
People [] Person
by Func (p, Q * person) bool
}

Func (PW Personwrapper) len () int {//rewrite Len () method
Return Len (pw.people)
}
Func (PW personwrapper) Swap (i, J int) {//override Swap () method
Pw.people[i], pw.people[j] = Pw.people[j], pw.people[i]
}
Func (PW personwrapper) Less (i, J int) bool {//rewrite less () method
Return pw.by (&pw.people[i], &pw.people[j])
}

Func Main () {
People: = [] person{
{"Zhang San", 12},
{"Li si", 30},
{"Wang Wu", 52},
{"Zhao Liu", 26},
}

Fmt. Println (People)

Sort. Sort (Personwrapper{people, func (p, q *person) bool {
Return Q.age < P.age//Age Descending sort
}})

Fmt. Println (People)
Sort. Sort (Personwrapper{people, func (p, q *person) bool {
Return P.name < Q.name//Name increment sort
}})

Fmt. Println (People)

}
Method 2 encapsulates the [] person and the benchmark CMP for comparison, forming the Personwrapper function and binding the Len, less, and Swap methods on it. actually sort. Sort (PW) sorts the people in PW, which is what is said earlier, that the go sort is not necessarily an array or a slice, but an array or a slice in an object.


Structure Sorting Method 3
Me Bright Method 2 is pretty good, the only drawback is that when used in main, the sort is exposed. The use of Sort, and the construction of Personwrapper. To make it easier to use in main, the me can simply encapsulate and construct a Sortperson method, as follows:


Package Main

Import (
"FMT"
"Sort"
)

Type person struct {
Name string//Name
Age int//Old
}

Type Personwrapper struct {
People [] Person
by Func (p, Q * person) bool
}

Type SortBy func (p, q *person) bool

Func (PW Personwrapper) len () int {//rewrite Len () method
Return Len (pw.people)
}
Func (PW personwrapper) Swap (i, J int) {//override Swap () method
Pw.people[i], pw.people[j] = Pw.people[j], pw.people[i]
}
Func (PW personwrapper) Less (i, J int) bool {//rewrite less () method
Return pw.by (&pw.people[i], &pw.people[j])
}


Func Sortperson (People [] person, by SortBy) {//Sortperson method
Sort. Sort (Personwrapper{people, by})
}

Func Main () {
People: = [] person{
{"Zhang San", 12},
{"Li si", 30},
{"Wang Wu", 52},
{"Zhao Liu", 26},
}

Fmt. Println (People)

Sort. Sort (Personwrapper{people, func (p, q *person) bool {
Return Q.age < P.age//Age Descending sort
}})

Fmt. Println (People)

Sortperson (People, func (p, q *person) bool {
Return P.name < Q.name//Name increment sort
})

Fmt. Println (People)

}
The Sortperson function is constructed on the basis of Method 2, which is used to pass a [] person and a CMP function.


Structure Sorting Method 4
Here is another implementation of the idea, can be said to be a variant of Method 1, 2.


Package Main

Import (
"FMT"
"Sort"
)

Type person struct {
Name string
Weight int
}

Type Personslice []person

Func (S Personslice) len () int {return Len (s)}
Func (S Personslice) Swap (i, J int) {S[i], s[j] = S[j], S[i]}

Type byname struct{Personslice}//Wrap Personslice up in byname

Func (S byname) Less (i, J int) bool {return s.personslice[i]. Name < S.personslice[j]. Name}//Will bind less to ByName


Type Byweight struct{Personslice}//Wrap Personslice up in Byweight
Func (S byweight) Less (i, J int) bool {return s.personslice[i]. Weight < S.personslice[j]. Weight}//bind less to Byweight

Func Main () {
s: = []person{
{"Apple", 12},
{"Pear", 20},
{"Banana", 50},
{"Orange", 87},
{"Hello", 34},
{"World", 43},
}

Sort. Sort (Byweight{s})
Fmt. Println ("People by Weight:")
Printpeople (s)

Sort. Sort (Byname{s})
Fmt. Println ("\npeople by Name:")
Printpeople (s)

}

Func printpeople (s []person) {
For _, O: = Range S {
Fmt. Printf ("%-8s (%v) \ n", O.name, O.weight)
}
}
The structure of the order, for the time being here. The first sort pair is only appropriate for one field, and the other three is for possible sorting based on multiple fields. Method 4 me think that each time to construct a byxxx, rather inconvenient, so much trouble, as Method 2 and the convenience of the method, directly into a CMP, and then okay. 2, 3 is not too big difference, 3 is simply encapsulated a bit, for users, it may be more convenient, but also less error.


The sort of go isn't over yet, if you're tired, take a break, =_=.

Go language Sort and search

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.