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] = e2. Go 语言实现函数原型:func insertionSort(a []int) []int
有个问题还是要问的:这个函数的参数是数组,还是切片?(答:切片,因为数组有固定长度)。
实现func insertionSort(a []int) []int {3. 程序演示例 1
// [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
下面这个 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 插入排序
这个测试 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 包来解决,有兴趣的同学可以研究一下。
版权声明
本文仅代表作者观点,不代表博信信息网立场。