[算法初步]之归并排序

[算法初步]之归并排序
##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()
	}





posted @ 2013-04-16 22:49  零界寒冰  阅读(189)  评论(0编辑  收藏  举报