1 描述
插入算法是生活中比较常用的算法,这个算法可以说所有人都用过,连小学生都会。只不过你平时用的时候没有意识到这个算法罢了。
比如说斗地主,这个大家都玩过吧。这个抓牌的过程其实就是一种插入排序的实现。
(当然可能略有些不同,斗地主是三个人抓牌,换排序肯可能就是你一个人抓一堆牌了)。
2 场景
首先来设定一个抓牌的场景,我们用1代表A,11代替J,13代替K。很明显,牌堆里面都是未排好序的,而抓牌后在你左手中的都是排序好的牌。
所以当前牌堆里面的牌是
- 左手:[] 牌堆:[3, 5, 1, 7, 6, 2, 11, 13, 4]。
ok,下面摸第一张牌,是一张3,放到左手,第一张牌本来就是排序好的,所以不用动了。
- 左手: [3] 牌堆:[5, 1, 7, 6, 2, 11, 13, 4]
继续摸第二张,右手抓了个5,还是比3大,直接放到3后面。
- 左手: [3,5] 牌堆:[1, 7, 6, 2, 11, 13, 4]
继续摸第二张,右手抓了个A,明显比3和5小需要排到3和5前面去,因此将3和5往右移一位,给A空出位置。然后将A插入大牌左手的牌堆空出的位置里。
- 左手: [空位,3 ,5] 牌堆:[ 7, 6, 2, 11, 13, 4] 右手[1]
- 左手: [1,3,5] 牌堆:[7, 6, 2, 11, 13, 4]
然后继续从牌堆里面拿牌,知道牌堆里面所有的牌都抓到左手中。
- 左手:[1, 2, 3, 4, 5, 6, 7, 11, 13] 牌堆:[]
3 go语言代码
下面用go语言对上面的算法进行实现。
和上面有些小不同:所有的数字其实都放在一个数组中排序,而且第一个数字默认已经是排序好的。
package main
import "fmt"
/*
* [插入排序]场景:
* 1 左边牌堆认为已经排好序(i),右边为未排序的牌(N-i)。
* 2 从右边取出下一张牌,在左边牌堆又后向前扫描比较。
* 3 比右边要插入牌大的话,则此牌往下移动一个位置。
* 4 重复步骤3,直到找到为新插入的牌调好位置
* 6 将手上的牌插到空留出的位置上。
* 7 重复步骤2,直到右边所有的牌都排序完成
*/
func sort(data *[9]int) {
var temp int
var i, j int
// 从右边堆取出牌到左边堆
for i = 1; i < len(data); i++ {
temp = data[i]
// 插入一张的操作,判断i-1张牌,比其的大后移,
for j = i - 1; j >= 0; j-- {
if data[j] > temp {
data[j+1] = data[j]
} else {
break
}
}
// 插入牌到移动后牌空出的位置上,在判断出的j位置之后
data[j+1] = temp
}
}
/**
* @param args
*/
func main() {
data := [9]int{3, 5 , 1, 7, 6, 2, 11, 13, 4}
sort(&data)
for i := 0; i < len(data); i++ {
fmt.Print(data[i])
fmt.Print(",")
}
}