go-sort排序

1. Overview

Package sort provides primitives for sorting slices and user-defined collections.

切片排序,或者是自定义集合的排序。
例子的话我觉得还是尽量看官方的,认准pkg.go.dev ,其他家博客的话例子举得不是很恰当。
我的话基本就是抄官方,加入一些自己的理解。

2. 实现
package main

import (
	"fmt"
	"sort"
)

type Person struct {
	Name string
	Age  int
}

func (p Person) String() string {
	return fmt.Sprintf("%s: %d", p.Name, p.Age)
}

// ByAge implements sort.Interface for []Person based on
// the Age field.
type ByAge []Person

func (a ByAge) Len() int           { return len(a) }
func (a ByAge) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a ByAge) Less(i, j int) bool { return a[i].Age < a[j].Age }

func main() {
	people := []Person{
		{"Bob", 31},
		{"John", 42},
		{"Michael", 17},
		{"Jenny", 26},
	}

	fmt.Println(people)
	// There are two ways to sort a slice. First, one can define
	// a set of methods for the slice type, as with ByAge, and
	// call sort.Sort. In this first example we use that technique.
	sort.Sort(ByAge(people))
	fmt.Println(people)

	// The other way is to use sort.Slice with a custom Less
	// function, which can be provided as a closure. In this
	// case no methods are needed. (And if they exist, they
	// are ignored.) Here we re-sort in reverse order: compare
	// the closure with ByAge.Less.
	sort.Slice(people, func(i, j int) bool {
		return people[i].Age > people[j].Age
	})
	fmt.Println(people)

}

主要是利用sort.Sort ,

// Sort sorts data.
// It makes one call to data.Len to determine n, and O(n*log(n)) calls to
// data.Less and data.Swap. The sort is not guaranteed to be stable.
func Sort(data Interface) {
	n := data.Len()
	quickSort(data, 0, n, maxDepth(n))
}

主要是接收一个data interface的,然后调用quickSort(这里的quickSort并不是纯的quicksort ,高度优化过的quicksort,跟自己实现那种还是要复杂上好几倍,就不展开了)

// A type, typically a collection, that satisfies sort.Interface can be
// sorted by the routines in this package. The methods require that the
// elements of the collection be enumerated by an integer index.
type Interface interface {
	// Len is the number of elements in the collection.
	Len() int
	// Less reports whether the element with
	// index i should sort before the element with index j.
	Less(i, j int) bool
	// Swap swaps the elements with indexes i and j.
	Swap(i, j int)
}

要现实三个函数,分别是Len(),Less(i,j) bool, Swap(i,j int),

完了之后调用就把切片,转换成排序的数据,强制转换一下,然后放入sort.Sort中即可。

sort.Sort(ByAge(people))

当然你可以定义ByOther。

这个例子后面还举了一个sort.Slice 直接跟一个匿名函数的用法

	// The other way is to use sort.Slice with a custom Less
	// function, which can be provided as a closure. In this
	// case no methods are needed. (And if they exist, they
	// are ignored.) Here we re-sort in reverse order: compare
	// the closure with ByAge.Less.
	sort.Slice(people, func(i, j int) bool {
		return people[i].Age > people[j].Age
	})

我觉得这种更接近java中的Arrays.sort(xxx,xxx),也不用写Swap和Len函数了,更实用一些,个人感觉。

3. 基础类型

比如int ,float64,String 这种有现成的函数就不用自己写了。

	sort.Ints()
	sort.Float64s()
	sort.Strings()
4. 小结

主要是实现3个函数,Len,Swap ,Less ,前面两个没什么说的,主要逻辑在Less 里面定义。就好了。
再付一个例子, https://www.luogu.com.cn/problem/P1093
典型的结构体排序。

package main

import (
	"bufio"
	"fmt"
	"os"
	"sort"
)

type Result struct {
	Chinese int
	Math int
	Eng int
	Id int
	Sum int
}
type Results []Result

func (r Results) Len() int{
	return len(r)
}
func (r Results)Swap(i,j int)  {
	r[i],r[j]=r[j],r[i]
}
func (r Results)Less(i,j  int) bool  {
	if r[i].Sum != r[j].Sum{
		return r[i].Sum > r[j].Sum
	}
	if r[i].Chinese != r[j].Chinese{
		return r[i].Chinese > r[j].Chinese
	}

	return r[i].Id < r[j].Id
}

func main() {
	var n int
	fmt.Scanf("%d",&n)
	res := make(Results,n)

	for i := 0; i < n; i++ {
		var a,b, c int

		fmt.Scanf("%d %d %d",&a,&b,&c)
		res[i]=Result{
			Chinese: a,
			Eng:     c,
			Math:    b,
			Id:      i+1,
			Sum:  a+b+c,
		}

	}
	sort.Sort(res)
	for i :=0;i<5;i++{
		fmt.Printf("%d %d\n",res[i].Id,res[i].Sum)
	}
	
}

但是洛谷的oj对golang的输入输出会有一些问题,acwing就可以ac。 不用纠结。洛谷还是用c++比较好一点。

posted @ 2020-12-02 01:12  过去的我  阅读(287)  评论(0编辑  收藏  举报