美文网首页Go算法
(2)Go实现递归排序及改进

(2)Go实现递归排序及改进

作者: 哥斯拉啊啊啊哦 | 来源:发表于2019-05-01 10:30 被阅读0次

递归排序的思想是分治法,即将问题划分为若干相互独立的个小问题,这些问题和该问题具有相同的特征,将这些小问题解决后,该问题也解决了。
按照这种思想,递归排序分为自上而下,自下而上2种
如下图示:


自上而下
自下而上
递归排序的实现
// 递归排序: 自上向下
func MergerSort1(arr []int) (resp []int) {
    l1 := len(arr)
    if l1 < 2 {
        return arr
    }
    mid := l1 / 2
    return Merger(MergerSort1(arr[:mid]), MergerSort1(arr[mid:]))
}

// 递归排序和插入排序相结合的排序
func MergerSort2(arr []int) (resp []int) {
    l1 := len(arr)

    if l1 < 100 {
        return InsertionSort(arr, l1)
    }

    mid := l1 / 2
    return Merger(MergerSort2(arr[:mid]), MergerSort2(arr[mid:]))
}

// 递归排序:自下向上
func MergerSortBU(arr []int) []int {
    l1 := len(arr)

    if l1 < 100 {
        return InsertionSort(arr, l1)
    }

    for sz := 1; sz < l1; sz += sz {
        for i := 0; i < l1-sz; i += sz + sz {
            copy(arr[i:min(i+sz+sz, l1)], Merger(
                arr[i:i+sz],
                arr[i+sz:min(i+sz+sz, l1)]))
        }
    }
    return arr
}

func Merger(arr1, arr2 []int) (resp []int) {
    l1 := len(arr1)
    l2 := len(arr2)

    i, j := 0, 0
    for i < l1 || j < l2 {
        switch {
        case j == l2:
            resp = append(resp, arr1[i])
            i++
        case i == l1:
            resp = append(resp, arr2[j])
            j++
            // 能到这里说明i<l1,j<l2
        case arr1[i] <= arr2[j]:
            resp = append(resp, arr1[i])
            i++
        default: // arr2[i] > arr2[j]
            resp = append(resp, arr2[j])
            j++
        }
    }
    return resp
}

// 插入排序
func InsertionSort(s []int, l int) []int {
    for i := 1; i < l; i++ {
        buf := s[i]
        var j int
        for j = i; j > 0 && s[j-1] > buf; j-- {
            s[j] = s[j-1]
        }
        s[j] = buf
    }
    return s
}

func min(i1, i2 int) int {
    if i1 > i2 {
        return i2
    }
    return i1
}
测试
const count = 1000

func main() {
    nums2 := [count]int{}
    for i := 0; i < count; i++ {
        nums2[i] = rand.Intn(count)
    }

    for i := 0; i < 4; i++ {
        nums3 := nums2
        nums := nums3[:]
        t := time.Now()
        switch i {
        case 0:
            nums = merger.InsertionSort(nums, count)
            fmt.Println("插入排序花费时间:", t.Sub(time.Now()))
            isTrue(nums)
        case 1:
            nums = merger.MergerSort1(nums)
            fmt.Println("递归排序花费时间:", t.Sub(time.Now()))
            isTrue(nums)
        case 2:
            nums = merger.MergerSort2(nums)
            fmt.Println("递归插入结合自上而下花费时间:", t.Sub(time.Now()))
            isTrue(nums)
        case 3:
            nums = merger.MergerSortBU(nums)
            fmt.Println("递归结合插入自下向上花费时间:", t.Sub(time.Now()))
            isTrue(nums)
        }
        fmt.Println("----")
    }
}

func isTrue(nums []int) {
    b := true
    for i := 1; i < count; i++ {
        if nums[i-1] > nums[i] {
            fmt.Println("排序错误", nums[i-1], nums[i])
            b = false
            break
        }
    }
    if b {
        fmt.Println("排序正确")
    }
}
// 分别令count=100,1000,10000
1)count=100
插入排序花费时间: -3.818µs
排序正确
----
递归排序花费时间: -46.523µs
排序正确
----
递归插入结合自上而下花费时间: -4.383µs
排序正确
----
递归结合插入自下向上花费时间: -29.861µs
排序正确

2)count=1000
插入排序花费时间: -221.893µs
排序正确
----
递归排序花费时间: -409.8µs
排序正确
----
递归插入结合自上而下花费时间: -110.996µs
排序正确
----
递归结合插入自下向上花费时间: -403.085µs

3)count=10000
插入排序花费时间: -22.420067ms
排序正确
----
递归排序花费时间: -8.385759ms
排序正确
----
递归插入结合自上而下花费时间: -6.942241ms
排序正确
----
递归结合插入自下向上花费时间: -6.024227ms
排序正确

结论:在数据量较小时,插入排序速度较快,在数据量大时候,递归排序较快,因此两者可以结合起来,
在数据量较大时,用递归排序,在数据量较小时,用插入排序,两者结合速度比单一的递归排序更快些,
而递归排序自上而下和自下而上两种速度差不多。
时间复杂度分析 //
插入排序为O(n^2),递归排序时间复杂度为nlogn

相关文章

  • (2)Go实现递归排序及改进

    递归排序的思想是分治法,即将问题划分为若干相互独立的个小问题,这些问题和该问题具有相同的特征,将这些小问题解决后,...

  • 看图说话排序算法之冒泡排序

    排序算法的种类非常多,这里总结冒泡排序和对冒泡排序的改进---快速排序的循环实现和递归实现。 一丶冒泡排序 假设待...

  • 排序

    八大排序算法 一、归并排序 递归及非递归的JAVA实现 二、快速排序 快排算法JAVA实现 三、堆排序 堆排序堆排...

  • 2020-08-21 算法合集

    1. 冒泡排序 2.选择排序 3. 插入排序 4. 希尔排序 5. 归并排序(递归实现) 6. 快速排序(递归实现...

  • 算法设计与分析——5.排序与树结构

    5.1 引言 5.2 递归与排序 5.2.1 选择排序 代码 5.1 选择排序的递归实现 代码 5.2 选择排序...

  • 三大排序算法

    归并排序[稳定的排序算法] 递归实现 非递归实现 快速排序[不稳定的排序算法] 堆排序[不稳定的排序算法]

  • 排序算法记录

    快排递归实现 非递归实现 3.排序算法的思想: (1)冒泡排序: 是相邻元素之间的比较和交换,两重循环O(n2);...

  • 3快速排序算法(Java语言)

    1.快速排序的特点: 1.分组,递归 2.代码实现: main方法: 排序方法...

  • 常见算法的 Python 实现

    二分法查找 非递归版本: 递归方法实现: 冒泡排序 选择排序

  • 数据结构——查找算法的实现与分析(二叉排序树)

    实验目的: 1.掌握二叉排序树的创建及查找算法(递归和非递归均可)。 实验要求: 1、创建一棵二叉排序树,并实现对...

网友评论

    本文标题:(2)Go实现递归排序及改进

    本文链接:https://www.haomeiwen.com/subject/ppyunqtx.html