[算法初步]之归并排序
##1 说明
归并排序
##2 场景
我一直觉得算法是在赌博中发明出来,比如这个归并算法,我们可以通过打麻将来模拟这个场景。
一般打麻将抓牌,都是先抓好,等牌都抓齐了牌之后才会进行整理。比如我们手里抓到了从一万到九万,一手未排序的万子。
* [3, 5 , 1, 7, 6, 2, 8, 9, 4]
麻将这玩意一般比较大,一手一堆放不下,所以我们分为2堆来整理。
* [[3, 5 , 1, 7][ 6, 2, 8, 9, 4]]
干脆分到底好了,继续分成2张为一堆的。
* [[[3, 5] [1, 7]] [[6, 2][ 8, 9] 4]]]
继续拆,知道拆分为一张为一堆
* [[[[3] [5]] [[1] [7]]] [[[6] [2]] [[8] [9]] [4]]]]
拆完牌了总要给拼起来啊。不然怎么出牌呢。好吧,我们就按每一堆来拼接,跟刚才拆牌逆着来。
在其他地方将刚才拆分的2堆牌拼好了再放回到原来的堆里,在这个拼接的过程中顺便把排序也给排好了。
第一次拼接
* [[[3, 5] [1, 7]] [[2, 6] [ 8, 9] 4]]]
继续拼接
* [[1, 3, 5, 7] [2, 4, 6, 8, 9]]
最后结果
* [1, 2, 3, 4, 5, 6, 7, 8, 9]
这个排序其实是一个将分治(分牌过程)和归并(拼牌过程)两个过程结合在一起。
##3 go语言实现:
package main
import "fmt"
/*
* 分治法的思想
* 将问题递归分为一个个的小问题。
* 解决最小的问题
* 将结果进行归并
* [归并排序]场景:
* 1 一堆N张散乱的麻将牌。
* 2 将这副牌分成相等的2堆,左边的为N/2,右边为N-N/2
* 3 继续递归分解,直到分到单一的一张牌
* 4 将分解后的单个牌按顺序循环归并,递归直到归并成一堆
*/
/*
* 归并方法 data 整个数组,归并左右两堆(【left,-middle】,【middle+1,-right】) left 归并左边数据的开始位置。
* midde 归并左边数据的结束位置。右边开始位置为middle+1 right 归并右边数据的结束位置
*/
func merge(data *[9]int, left int, middle int, right int) {
// 创建2个临时数组来存储左右两边的数据,长度分别为middle - left + 1,和right - middle
length1 := middle - left + 1
length2 := right - middle
leftTemp := make([]int, length1)
rightTemp := make([]int, length2)
// 复制数据到临时数组
i := 0
j := 0
for i = 0; i < length1; i++ {
leftTemp[i] = data[left+i]
}
for j = 0; j < length2; j++ {
rightTemp[j] = data[middle+1+j]
}
// 归并,第一次归并到一组数据已经为空的情况,第二次将剩下的一组数据复制到数据中。
k := left
for i, j = 0, 0; i < length1 && j < length2; {
if leftTemp[i] < rightTemp[j] {
data[k] = leftTemp[i]
k++
i++
} else {
data[k] = rightTemp[j]
k++
j++
}
}
if i == length1 {
for j < length2 {
data[k] = rightTemp[j]
k++
j++
}
}
if j == length2 {
for i < length1 {
data[k] = leftTemp[i]
k++
i++
}
}
}
/*
* 排序方法,先分治排序,然后合并
*/
func sort(data *[9]int, left int, right int) {
// left=right时候,长度为1
if left < right {
middle := (left + right) / 2
// 分治,将date的【left--middel】来进行分解排序。最后返回的结果是全部排序好的。
sort(data, left, middle)
// 分治,将date的【middel--right】来进行分解排序。最后返回的结果是全部排序好的。
sort(data, middle+1, right)
// 组合,将数据的【left--middel】和【middel--right】进行归并
merge(data, left, middle, right)
}
}
func main() {
data := [9]int{3, 5, 1, 7, 6, 2, 8, 9, 4}
sort(&data, 0, len(data)-1)
for i := 0; i < len(data); i++ {
fmt.Print(data[i], ",")
}
fmt.Println()
}