>백엔드 개발 >Golang >golang에서 정렬 패키지를 구현하는 방법

golang에서 정렬 패키지를 구현하는 방법

尚
원래의
2019-12-16 15:16:183026검색

golang에서 정렬 패키지를 구현하는 방법

정렬 패키지는 삽입 정렬이라는 3가지 기본 정렬 알고리즘을 구현합니다. 퀵 정렬과 힙 정렬. 다른 언어와 마찬가지로 이 세 가지 메서드는 공개되지 않으며 정렬 패키지에서 내부적으로만 사용됩니다.

그래서 사용자는 정렬 패키지를 사용하여 정렬할 때 어떤 정렬 방법을 사용할지 고려할 필요가 없습니다. sort.Interface에 정의된 세 가지 메서드가 있습니다. 데이터 길이를 가져오는 Len() 메서드입니다. 두 요소의 위치를 ​​교환하는 Less() 메서드와 Swap() 메서드를 사용하면 데이터 수집을 원활하게 정렬할 수 있습니다. 정렬 패키지는 실제 데이터를 기반으로 효율적인 정렬 알고리즘을 자동으로 선택합니다.

type Interface interface {
    // 返回要排序的数据长度
    Len() int
    //比较下标为i和j对应的数据大小,可自己控制升序和降序        
Less(i, j int) bool
    // 交换下标为i,j对应的数据
    Swap(i, j int)
}

sort.Interface를 구현하는 모든 유형(일반적으로 컬렉션)은 이 패키지의 메서드를 사용하여 정렬할 수 있습니다. 이러한 메서드를 사용하려면 컬렉션 내에 나열된 요소의 인덱스가 정수여야 합니다.

여기서는 구현을 직접 설명하기 위해 소스 코드를 사용합니다:

1 소스 코드의 예:

type Person struct {
    Name string
    Age  int
}

type ByAge []Person
//实现了sort接口中的三个方法,则可以使用排序方法了
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 Example() {
    people := []Person{
        {"Bob", 31},
        {"John", 42},
        {"Michael", 17},
        {"Jenny", 26},
    }

    fmt.Println(people)
    sort.Sort(ByAge(people)) //此处调用了sort包中的Sort()方法,我们看一下这个方法
    fmt.Println(people)

    // Output:
    // [Bob: 31 John: 42 Michael: 17 Jenny: 26]
    // [Michael: 17 Jenny: 26 Bob: 31 John: 42]
}

2. 인터페이스) method# 🎜🎜#

//sort包只提供了这一个公开的公使用的排序方法,
func Sort(data Interface) {
    // Switch to heapsort if depth of 2*ceil(lg(n+1)) is reached.
    //如果元素深度达到2*ceil(lg(n+1))则选用堆排序
    n := data.Len()
    maxDepth := 0
    for i := n; i > 0; i >>= 1 {
        maxDepth++
    }
    maxDepth *= 2
    quickSort(data, 0, n, maxDepth)
}
//快速排序
//它这里会自动选择是用堆排序还是插入排序还是快速排序,快速排序就是
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) //堆排序方法,a=0,b=n
            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)
    }
}
//堆排序
func heapSort(data Interface, a, b int) {
    first := a
    lo := 0
    hi := b - a

    // Build heap with greatest element at top.
    //构建堆结构,最大的元素的顶部,就是构建大根堆
    for i := (hi - 1) / 2; i >= 0; i-- {
        siftDown(data, i, hi, first)
    }

    // Pop elements, largest first, into end of data.
    //把first插入到data的end结尾
    for i := hi - 1; i >= 0; i-- {
        data.Swap(first, first+i) //数据交换
        siftDown(data, lo, i, first) //堆重新筛选
    }
}
// siftDown implements the heap property on data[lo, hi).
// first is an offset into the array where the root of the heap lies.
func siftDown(data Interface, lo, hi, first int) {
    //hi为数组的长度
    //这里有一种做法是把跟元素给取到存下来,但是为了方法更抽象,省掉了这部,取而代之的是在swap的时候进行相互交换
    root := lo  //根元素的下标
    for {
        child := 2*root + 1 //左叶子结点下标
        //控制for循环介绍,这种写法更简洁,可以查看我写的堆排序的文章
        if child >= hi { 
            break
        }
        //防止数组下标越界,判断左孩子和右孩子那个大
        if child+1 < hi && data.Less(first+child, first+child+1) {  
            child++
        }
        //判断最大的孩子和根元素之间的关系
        if !data.Less(first+root, first+child) {
            return
        }
        //如果上面都 满足,则进行数据交换
        data.Swap(first+root, first+child)
        root = child
    }
}

더 많은 golang 지식을 알고 싶다면

golang tutorial 컬럼을 주목해주세요.

위 내용은 golang에서 정렬 패키지를 구현하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.