归并排序的 Go 语言实现和优化

栏目: 编程工具 · 发布时间: 5年前

内容简介:查看完整的代码,不了解归并排序的可以查看

查看完整的代码, 点击这里

不了解归并 排序 的可以查看 百度百科的分析

归并排序的实现

基本实现

package main

import "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)
}

以上所述就是小编给大家介绍的《归并排序的 Go 语言实现和优化》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Unity 3D游戏开发(第2版)

Unity 3D游戏开发(第2版)

宣雨松 / 人民邮电出版社 / 2018-9 / 89.00元

Unity 是一款市场占有率非常高的商业游戏引擎,横跨25 个主流游戏平台。本书基于Unity 2018,结合2D 游戏开发和3D 游戏开发的案例,详细介绍了它的方方面面,内容涉及编辑器、游戏脚本、UGUI 游戏界面、动画系统、持久化数据、静态对象、多媒体、资源加载与优化、自动化与打包等。 本书适合初学者或者有一定基础的开发者阅读。一起来看看 《Unity 3D游戏开发(第2版)》 这本书的介绍吧!

MD5 加密
MD5 加密

MD5 加密工具

SHA 加密
SHA 加密

SHA 加密工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具