Go语言实现归并排序

3,067 阅读2分钟

归并排序

思想:

归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。归并排序是一种稳定的排序方法。 --百度百科

时间复杂度:O(nlogn)

稳定性:稳定

Go语言实现

分治规则

func mergeSort(arr []int,left int,right int){
    if right > left{
        mid := (left+right)/2
        mergeSort(arr,left,mid) // 左边分治
        mergeSort(arr,mid+1,right) // 右边分治
        // 分治完则合并
        merge(arr,left,mid,right)
    }
}

合并规则

func merge(arr []int,left int,mid int,right int){
    var temp = make([]int,len(arr)) // 开辟一个临时数组,存放合并之后的数组
    var pointer1 = left // 左边的指针 指向左边数组的第一个元素
    var pointer2 = mid+1 // 右边的指针 指向右边数组的第一个元素
    var loc = left // 用于记录临时数组当前指针指向
    for pointer1<=mid && pointer2<=right{ //一直遍历左右两个数组
        if arr[pointer1] < arr[pointer2] { // 较小的元素先进入
            temp[loc] = arr[pointer1]
            pointer1++ // 左边数组指向下一位
        }else{
            temp[loc] = arr[pointer2]
            pointer2++ // 右边数组指向下一位
        }
        loc++ // 插入一个元素后,临时数组位置指向下一位
    }
    // 虽然左右两边数组都已经插入到临时数组中,但左右两边尾部的元素依旧没有插入,因此,这里还需要再插入一次
    for pointer1 <= mid { // 左边继续合并
        temp[loc] = arr[pointer1]
        loc++
        pointer1++
    }
    for pointer2 <= right { // 右边继续合并
        temp[loc] = arr[pointer2]
        loc++
        pointer2++
    }
    // 此时,并操作已经完成,现在需要把临时数组重新截取值
    for i:=left;i<=right;i++{
        arr[i]=temp[i]
    }
}

//测试

func main() {
	var data = []int{3, 5, 75, 34, 8, 31, 44, 76, 87, 25, 73, 11}
	mergeSort(data, 0, len(data)-1)
	fmt.Println(data) //[3 5 8 11 25 31 34 44 73 75 76 87]
}

总结

归并排序是分治思想的运用,其核心是将需要排序的数组按照一定规则分下去,分到无法再分的时候再对左右两边数组元素进行对比,再以小的排在前面大的排在后面(或大的排在前面小的排在后面)的方式合并成一个数组,实现有序