sorter 接口排序代码分析

一下这段代码来自《Go 入门指南》第十一章第七节 “第一个例子:使用 Sorter 接口排序”,认真理解阅读里面的代码对理解接口和方法集有很大的帮助,这里也作为我自己的学习批注,将这段代码,和自己的注释一并放在此处作为学习笔记。

更详细的内容请点击上面的链接进入图书官网进行学习,这里只是作为我自己的学习笔记。

sort.go
该文件中定义了 Sorter 接口和相关类型,以及实现的方法

package sort

// 任何排序算法只需要试下下列方法即可
type Sorter interface {
    
    
	// 判断被排序的数组长度
    Len() int
	// 比较元素大小
    Less(i, j int) bool
	// 位置交换
    Swap(i, j int)
}

// 此处采用冒泡排序法
// 传入的参数为接口类型变量
func Sort(data Sorter) {
    
    
	// 如果你用其他的排序算法,仅仅只需要改变下面两个 for 的代码
    for pass := 1; pass < data.Len(); pass++ {
    
    
        for i := 0; i < data.Len()-pass; i++ {
    
    
            if data.Less(i+1, i) {
    
    
                data.Swap(i, i+1)
            }
        }
    }
}

// 判断是否排序
func IsSorted(data Sorter) bool {
    
    
    n := data.Len()
	// 遍历并比较相邻两个元素的大小
    for i := n - 1; i > 0; i-- {
    
    
        if data.Less(i, i-1) {
    
    
            return false
        }
    }
    return true
}

// 将排序算法推广到 int, string, ...
type IntArray []int

// 传入int切片类型的参数
func (p IntArray) Len() int           {
    
     return len(p) }
func (p IntArray) Less(i, j int) bool {
    
     return p[i] < p[j] }
func (p IntArray) Swap(i, j int)      {
    
     p[i], p[j] = p[j], p[i] }

type StringArray []string

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

// 一个包装器,使得实现更方便直观
// Sort 中传入参数为 Sorter 接口变量,因为 IntArray 自定义类型实现了这个接口所以是 Sorter 接口类型,而直接用 a
// 不行,因为 a 是 []int,而 []int 没有实现 sorter 这个接口类型
func SortInts(a []int)       {
    
     Sort(IntArray(a)) }
func SortStrings(a []string) {
    
     Sort(StringArray(a)) }

func IntsAreSorted(a []int) bool       {
    
     return IsSorted(IntArray(a)) }
func StringsAreSorted(a []string) bool {
    
     return IsSorted(StringArray(a)) }

sortmain.go
main 函数放在这里

package main

import (
    "./sort"
    "fmt"
)

func ints() {
    
    
    data := []int{
    
    74, 59, 238, -784, 9845, 959, 905, 0, 0, 42, 7586, -5467984, 7586}
    a := sort.IntArray(data) //conversion to type IntArray
	// 此处的 sort 是导入的 sort 包
    sort.Sort(a)
    if !sort.IsSorted(a) {
    
    
        panic("fails")
    }
    fmt.Printf("The sorted array is: %v\n", a)
}

func strings() {
    
    
    data := []string{
    
    "monday", "friday", "tuesday", "wednesday", "sunday", "thursday", "", "saturday"}
    a := sort.StringArray(data)
    sort.Sort(a)
    if !sort.IsSorted(a) {
    
    
        panic("fail")
    }
    fmt.Printf("The sorted array is: %v\n", a)
}

type day struct {
    
    
    num       int
    shortName string
    longName  string
}
// 这个和 sort.go 中的 IntArray ,StringArray 一样
type dayArray struct {
    
    
    data []*day
}

func (p *dayArray) Len() int           {
    
     return len(p.data) }
func (p *dayArray) Less(i, j int) bool {
    
     return p.data[i].num < p.data[j].num }
func (p *dayArray) Swap(i, j int)      {
    
     p.data[i], p.data[j] = p.data[j], p.data[i] }

func days() {
    
    
    Sunday    := day{
    
    0, "SUN", "Sunday"}
    Monday    := day{
    
    1, "MON", "Monday"}
    Tuesday   := day{
    
    2, "TUE", "Tuesday"}
    Wednesday := day{
    
    3, "WED", "Wednesday"}
    Thursday  := day{
    
    4, "THU", "Thursday"}
    Friday    := day{
    
    5, "FRI", "Friday"}
    Saturday  := day{
    
    6, "SAT", "Saturday"}
	// day 指针类型的切片
    data := []*day{
    
    &Tuesday, &Thursday, &Wednesday, &Sunday, &Monday, &Friday, &Saturday}
    a := dayArray{
    
    data}
    sort.Sort(&a)
    if !sort.IsSorted(&a) {
    
    
        panic("fail")
    }
    for _, d := range data {
    
    
        fmt.Printf("%s ", d.longName)
    }
    fmt.Printf("\n")
}

func main() {
    
    
    ints()
    strings()
    days()
}

Guess you like

Origin blog.csdn.net/qq_34902437/article/details/121105072