38

GO语言学习笔记6-Sort的使用

 4 years ago
source link: https://studygolang.com/articles/25067
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

GoLang标准库的sort包提供了排序切片和用户自定义数据集以及相关功能的函数。

Sort操作的对象通常是一个slice,需要满足三个基本的接口,并且能够使用整数来索引。

1.sort实现原理

Sort排序的函数原型如下所示:

(1)Sort

// 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))
}

(2) interface

// 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)
}

(3) quickSort

func quickSort(data Interface, a, b, maxDepth int) {
    for b-a > 12 { // Use ShellSort for slices <= 12 elements
        if maxDepth == 0 {
            heapSort(data, a, b)
            return
        }
        maxDepth--
        mlo, mhi := doPivot(data, a, b)
        // Avoiding recursion on the larger subproblem guarantees
        // a stack depth of at most lg(b-a).
        if mlo-a < b-mhi {
            quickSort(data, a, mlo, maxDepth)
            a = mhi // i.e., quickSort(data, mhi, b)
        } else {
            quickSort(data, mhi, b, maxDepth)
            b = mlo // i.e., quickSort(data, a, mlo)
        }
    }
    if b-a > 1 {
        // Do ShellSort pass with gap 6
        // It could be written in this simplified form cause b-a <= 12
        for i := a + 6; i < b; i++ {
            if data.Less(i, i-6) {
                data.Swap(i, i-6)
            }
        }
        insertionSort(data, a, b)
    }
}

2.Sort内部 []int排序

type IntSlice []int
// 获取此 slice 的长度
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] }

// Sort is a convenience method.
func (p IntSlice) Sort() { Sort(p) }

3.代码实现

Olymic Game 这道题采用Sort排序的实现方法如下:

package main

import (
    "fmt"
    "sort"
    "strings"
)

type MedalNum struct {
    name string
    gold int
    silver int
    bronze int
}

type MedalNumList []MedalNum

func (m MedalNumList) Len() int {
    return len(m)
}

// 奖牌数降序,国家名称字典序
func (m MedalNumList) Less(i, j int) bool {
    if m[i].gold > m[j].gold {
        return true
    } else if m[i].gold == m[j].gold {
        if m[i].silver > m[j].silver {
            return true
        } else if m[i].silver == m[j].silver {
            if m[i].bronze > m[j].bronze {
                return true
            } else if m[i].bronze == m[j].bronze {
                if strings.Compare(m[i].name, m[j].name) < 0 {
                    return true
                }
            }
        }

    }
    return false
}

func (m MedalNumList) Swap(i, j int) {
    m[i], m[j] = m[j], m[i]
}

func main() {
    var n int

    _, _ = fmt.Scan(&n)

    var medal MedalNumList

    var nameI string
    var goldI, sliverI, bronzeI int

    i := 0
    for {
        if i == n {
            break
        }
        _, err := fmt.Scanln(&nameI, &goldI, &sliverI, &bronzeI);

        if err != nil {
            break
        } else {
            medal = append(medal, MedalNum{name:nameI, gold:goldI, silver:sliverI, bronze:bronzeI})
        }

        i++
    }

    sort.Sort(medal)

    for _, m := range medal {
        fmt.Println(m.name)
    }

}

Compare是字符串比较函数,函数原型如下所示:

// Compare returns an integer comparing two strings lexicographically.
// The result will be 0 if a==b, -1 if a < b, and +1 if a > b.
func Compare(a, b string) int {
    if a == b {
        return 0
    }
    if a < b {
        return -1
    }
    return +1
}

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK