歸併排序的 Go 語言實現和最佳化

來源:互聯網
上載者:User

查看完整的代碼,點擊這裡

不瞭解歸併排序的可以查看百度百科的分析

歸併排序的實現

基本實現

package mainimport "fmt"// 合并 [l,r] 兩部分資料,mid 左半部分的終點,mid + 1 是右半部分的起點func merge(arr []int, l int, mid int, r int) {   // 因為需要直接修改 arr 資料,這裡首先複製 [l,r] 的資料到新的數組中,用於賦值操作     temp := make([]int, r-l+1)    for i := l; i <= r; i++ {        temp[i-l] = arr[i]    }       // 指向兩部分起點    left := l    right := mid + 1    for i := l; i <= r; i++ {       // 左邊的點超過中點,說明只剩右邊的資料        if left > mid {            arr[i] = temp[right-l]            right++        // 右邊的資料超過終點,說明只剩左邊的資料        } else if right > r {            arr[i] = temp[left-l]            left++       // 左邊的資料大於右邊的資料,選小的數字        } else if temp[left - l] > temp[right - l] {            arr[i] = temp[right - l]            right++        } else {            arr[i] = temp[left - l]            left++        }    }}func MergeSort(arr []int, l int, r int) {    if l >= r {        return    }    // 遞迴向下    mid := (r + l) / 2    MergeSort(arr, l, mid)    MergeSort(arr, mid+1, r)    // 歸併向上    merge(arr, l, mid, r)}func main() {    arr := []int{3, 1, 2, 5, 6, 43, 4}    MergeSort(arr, 0, len(arr)-1)    fmt.Println(arr)}

最佳化點

  • 只有左邊資料的最大值大於右邊資料的最小值時才需要歸併

    舉例:現在需要歸併的左右部分為 [1,3] 和 [4,5],則不需要進行「並」的操作。而 [1,4] 和 [3,5] 則需要進行「並」為 [1,3,4,5]

  • 當二分資料到一定階段,可以使用插入排序而不是繼續向下二分

    雖然複雜度上看 nlogn 始終大於 n^2,但是都忽略了常數項,而歸併的常數項大於插入排序,所以當 n 足夠小時,插入排序速度更快

    以下是結合最佳化點的程式更改:

package main    import "fmt"    func merge(arr []int, l int, mid int, r int) {    temp := make([]int, r-l+1)    for i := l; i <= r; i++ {        temp[i-l] = arr[i]    }        left := l    right := mid + 1        for i := l; i <= r; i++ {        if left > mid {            arr[i] = temp[right-l]            right++        } else if right > r {            arr[i] = temp[left-l]            left++        } else if temp[left - l] > temp[right - l] {            arr[i] = temp[right - l]            right++        } else {            arr[i] = temp[left - l]            left++        }    }}    func MergeSort(arr []int, l int, r int) {    // 第二步最佳化,當資料規模足夠小的時候,可以使用插入排序    if r - l <= 15 {        // 對 l,r 的資料執行插入排序        for i := l + 1; i <= r; i++ {            temp := arr[i]            j := i            for ; j > 0 && temp < arr[j-1]; j-- {                arr[j] = arr[j-1]            }            arr[j] = temp        }        return    }        mid := (r + l) / 2    MergeSort(arr, l, mid)    MergeSort(arr, mid+1, r)        // 第一步最佳化,左右兩部分已排好序,只有當左邊的最大值大於右邊的最小值,才需要對這兩部分進行merge操作    if arr[mid] > arr[mid + 1] {        merge(arr, l, mid, r)    }}    func main() {    arr := []int{3, 1, 2, 5, 6, 43, 4}    MergeSort(arr, 0, len(arr)-1)        fmt.Println(arr)}
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.