037-插入排序

这次来一点实战的,让你熟练掌握数组,slice. 所以选来选去,就选一个最简单的插入排序算法吧。

1. 插入排序思路

这个算法相信学计算机的同学都相当熟悉,不过还是先来预热一下,看看它的基本思路。


这里写图片描述
图1 插入排序

假设数组 a,大小为 8,其中 a[0...3] 都已经有序,此时我们需要将第 i 个元素(第 4 个)插入到已排序的合适的部分。最简单直接的做法就是从后向前找一个小于等于它的元素。

在图 1 中,需要先将元素 9 复制到临时空间 e 中,接下来:

  • a[3] <= e ? 不成立,a[4] = a[3]
  • a[2] <= e ? 不成立,a[3] = a[2]
  • a[1] <= e ? 成立, a[2] = e

2. Go 语言实现

  • 函数原型:func insertionSort(a []int) []int

有个问题还是要问的:这个函数的参数是数组,还是切片?(答:切片,因为数组有固定长度)。

  • 实现
func insertionSort(a []int) []int {
    // [3,5,6,8][1,8,0,3,9,2]
    //        |  |
    //        j  i
    for i := 0; i < len(a); i++ {
        e := a[i]
        j := i - 1
        for j >= 0 {
            if e < a[j] {
                a[j+1] = a[j]
            } else {
                break
            }
            j--
        }
        a[j+1] = e
    }
    return a
}

3. 程序演示

  • 例 1

下面这个 demo 用来测试我们写的 insertSort 函数的功能。注意 a1 到 a11 是数组,它不是切片,还记得怎么转成切片吗?

func main() {
    a1 := [...]int{}
    a2 := [...]int{3}
    a3 := [...]int{1, 2, 3}
    a4 := [...]int{1, 3, 2}
    a5 := [...]int{2, 1, 3}
    a6 := [...]int{2, 3, 1}
    a7 := [...]int{3, 1, 2}
    a8 := [...]int{3, 2, 1}
    a9 := [...]int{3, 1, 1, 1}
    a10 := [...]int{1, 1, 1, 1}
    a11 := [...]int{1, 9, 5, 2, 9, 1, 5, -5, 2, 9, 5, 1, 9, 2, 1}

    fmt.Printf("a1 = %v\n", a1)
    fmt.Printf("a2 = %v\n", a2)
    fmt.Printf("a3 = %v\n", a3)
    fmt.Printf("a4 = %v\n", a4)
    fmt.Printf("a5 = %v\n", a5)
    fmt.Printf("a6 = %v\n", a6)
    fmt.Printf("a7 = %v\n", a7)
    fmt.Printf("a8 = %v\n", a8)
    fmt.Printf("a9 = %v\n", a9)
    fmt.Printf("a10 = %v\n", a10)
    fmt.Printf("a11 = %v\n", a11)

    insertionSort(a1[:])
    insertionSort(a2[:])
    insertionSort(a3[:])
    insertionSort(a4[:])
    insertionSort(a5[:])
    insertionSort(a6[:])
    insertionSort(a7[:])
    insertionSort(a8[:])
    insertionSort(a9[:])
    insertionSort(a10[:])
    insertionSort(a11[:])
    fmt.Println()

    fmt.Printf("a1 = %v\n", a1)
    fmt.Printf("a2 = %v\n", a2)
    fmt.Printf("a3 = %v\n", a3)
    fmt.Printf("a4 = %v\n", a4)
    fmt.Printf("a5 = %v\n", a5)
    fmt.Printf("a6 = %v\n", a6)
    fmt.Printf("a7 = %v\n", a7)
    fmt.Printf("a8 = %v\n", a8)
    fmt.Printf("a9 = %v\n", a9)
    fmt.Printf("a10 = %v\n", a10)
    fmt.Printf("a11 = %v\n", a11)
}


这里写图片描述
图2 插入排序

  • 例 2

这个测试 case 传入的参数很奇怪,我只是传递了不完整的切片给插入排序函数,看看它输出什么?

func main() {
    a := [...]int{8, 6, 10, 7, 9, 3, 4, 5, 2, 1}

    fmt.Printf("a = %v\n", a)

    insertionSort(a[:5])
    insertionSort(a[5:])
    fmt.Println()

    fmt.Printf("a = %v\n", a)
}


这里写图片描述
图3 运行结果

看起来很厉害是不是?我们甚至可以对一个数组的局部进行排序,而且相当方便。不是说其它语言做不到,至少没 Go 这么方便。

4. 总结

  • 掌握数组和切片,加深理解

有同学可能要问,为啥要自己写排序算法,Go 里没有提供排序的函数吗???放心,写排序的目的是为了让你对数组和切片加深印象。真正工作里有排序的需求,可以直接使用 Go 提供的 sort 包来解决,有兴趣的同学可以研究一下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值