Golang 数据排序

sort.Interface 接口

这个接口是 sort 包的核心,它有3个方法。这是 Golang 很酷的一个特性,只要数据类型满足 sort.Interface 接口,就可以用sort包的函数进行排序。

// 一个满足sort.Interface接口的(集合)类型可以被本包的函数进行排序。
// 方法要求集合中的元素可以被整数索引。
type Interface interface {
    // Len方法返回集合中的元素个数
    Len() int
    // Less方法报告索引i的元素是否比索引j的元素小
    Less(i, j int) bool
    // Swap方法交换索引i和j的两个元素
    Swap(i, j int)
}

Example1

package main

import (
    "fmt"
    "sort"
)

//自定义一个类型
type ints []int

func (s ints) Len() int           { return len(s) }
func (s ints) Less(i, j int) bool { return s[i] < s[j] }
func (s ints) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }

func main() {
    nums := []int{9, 8, 5, 4, 7, 6, 3, 0, 1, 2}

    sort.Sort(ints(nums)) //进行排序
    fmt.Println(nums)
}

Output: [0 1 2 3 4 5 6 7 8 9]

Example2

package main

import (
    "fmt"
    "sort"
)

type Person struct {
    Name string
    Age  int
}

type Persons []Person

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

func main() {
    p := []Person{Person{"Lily", 20}, Person{"Bing", 18}, Person{"Tom", 23}, Person{"Vivy", 16}, Person{"John", 18}}

    sort.Sort(sort.Reverse(Persons(p))) //sort.Reverse 生成递减序列
    fmt.Println(p)
}

Output: [{Tom 23} {Lily 20} {Bing 18} {John 18} {Vivy 16}]

sort 包内置的排序方法

So easy ! 看了2个例子你应该明白了吧!

方法 说明
func Sort(data Interface) 递增排序,不能保证排序的稳定性,即不保证相等元素的相对次序不变。用的是快速排序算法
func Stable(data Interface) 递增排序,保证排序的稳定性,相等元素的相对次序不变。用的是插入排序算法
func IsSorted(data Interface) bool 判断data是否已经被递增排序
func Reverse(data Interface) Interface 对该接口排序可生成递减序列
func Ints(a []int) 将 []int 排序为递增顺序
func IntsAreSorted(a []int) bool 检查 []int 是否已排序为递增顺序
func Float64s(a []float64) 将 []float64 排序为递增顺序
func Float64sAreSorted(a []float64) bool 检查 []float64 是否已排序为递增顺序
func Strings(a []string) 将 []string 排序为递增顺序
func StringsAreSorted(a []string) bool 检查 []string 是否已排序为递增顺序

Example:

s := []int{5, 2, 6, 3, 1, 4} // unsorted
sort.Ints(s)
fmt.Println(s)

Output: [1 2 3 4 5 6]

使用自定义排序算法

package main

import (
    "fmt"
    "sort"
)

//bubbleSort 冒泡排序
func bubbleSort(data sort.Interface) {
    r := data.Len() - 1
    for i := 0; i < r; i++ {
        for j := r; j > i; j-- {
            if data.Less(j, j-1) {
                data.Swap(j, j-1)
            }
        }
    }
}

//insertSort 插入排序
func insertSort(data sort.Interface) {
    r := data.Len() - 1
    for i := 1; i <= r; i++ {
        for j := i; j > 0 && data.Less(j, j-1); j-- {
            data.Swap(j, j-1)
        }
    }
}

//selectSort 选择排序
func selectSort(data sort.Interface) {
    r := data.Len() - 1
    for i := 0; i < r; i++ {
        min := i
        for j := i + 1; j <= r; j++ {
            if data.Less(j, min) {
                min = j
            }
        }
        data.Swap(i, min)
    }
}

func main() {
    nums := []int{9, 8, 5, 4, 7, 6, 3, 0, 1, 2}
    ints := sort.IntSlice(nums) //IntSlice给[]int添加方法以满足Interface接口,以便排序为递增序列。

    bubbleSort(ints) //使用冒泡排序
    fmt.Println(ints)
}

output: [0 1 2 3 4 5 6 7 8 9]

搜索

搜索和排序是2兄弟,搜索是从已经排序的数据中返回数据的位置。

方法 说明
func SearchInts(a []int, x int) int SearchInts在递增顺序的a中搜索x,返回x的索引。如果查找不到,返回值是x应该插入a的位置(以保证a的递增顺序),返回值可以是len(a)。是Search函数函数的包装。
func SearchFloat64s(a []float64, x float64) int 同上,只是数据类型不同
func SearchStrings(a []string, x string) int 同上,只是数据类型不同
func Search(n int, f func(int) bool) int 采用二分法搜索找到[0, n)区间内最小的满足f(i)==true的值i。返回找到的索引i,如果没有符合要求的索引,则返回 n。

Example1:[]int 搜索

package main

import (
    "fmt"
    "sort"
)

func main() {
    data := sort.IntSlice{9, 5, 3, 25, 1, 5, 64, 45, 21, 48, 55}
    data.Sort() // 等价于调用 sort.Sort,搜索前需要先排序。
    fmt.Println(data)

    x := 5
    i := data.Search(x) // 等价于调用 sort.SearchInts
    fmt.Printf("%v is present at data[%d]\n", x, i)
}

output:
[1 3 5 5 9 21 25 45 48 55 64]
5 is present at data[2]

Example2: []struct 搜索

package main

import (
    "fmt"
    "sort"
)

type Person struct {
    Name string
    Age  int
}

type Persons []Person

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

func main() {
    p := []Person{Person{"Lily", 20}, Person{"Bing", 18}, Person{"Tom", 23}, Person{"Vivy", 16}, Person{"John", 18}}
    sort.Sort(sort.Reverse(Persons(p))) //sort.Reverse 生成递减序列
    fmt.Println(p)

    x := 18
    i := sort.Search(len(p), func(i int) bool {
        //如果使用 p[i].Age == x,则找不到索引时返回的是n,而不是列表应该插入的位置,会破坏列表顺序。
        //在升序列表中使用 p[i].Age >= x,则找不到索引时返回接近x的位置,以保证列表的递增顺序
        //在降序列表中使用 p[i].Age <= x,则找不到索引时返回接近x的位置,以保证列表的递减顺序
        return p[i].Age <= x
    })
    fmt.Println(i)
}

output:
[{Tom 23} {Lily 20} {Bing 18} {John 18} {Vivy 16}]
2


参考:https://my.oschina.net/evilunix/blog/370676

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,599评论 18 139
  • 背景 一年多以前我在知乎上答了有关LeetCode的问题, 分享了一些自己做题目的经验。 张土汪:刷leetcod...
    土汪阅读 12,724评论 0 33
  • ¥开启¥ 【iAPP实现进入界面执行逐一显】 〖2017-08-25 15:22:14〗 《//首先开一个线程,因...
    小菜c阅读 6,358评论 0 17
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,581评论 18 399
  • 而你撑伞拥我入怀中 ——我的一个道姑朋友(改 编) 那日,她上山采药。下山途中,天空布满金丝,绵绵细...
    旧颜er阅读 1,630评论 9 55