# 归并排序 

* **介绍**
  * `归并特性`
    * 一个列表两段有序,通过归并实现合并成一段有序列表。
  * 复杂度O(n log(n))
  * 思路:先分解在合并
  * 过程: 
    * 分解:将列表越分越小,直至分成一个元素;
    * 终止条件:一个元素是有序的;
    * 合并:将两个有序列表归并,列表越来越大。
  * 关键字:
    * 分解
    * 归并
  * 存在问题
    * 需要额外的内存开销
    * 快速排序 `>` 归并排序 `>` 堆排序 
* **原理**
  * 通过对若干个有序结点序列的归并来实现排序。
  * 所谓归并是指将若干个已排好序的部分合并成一个有序的部分。
* **代码**

```go
/**
MergeSort 实现归并排序(前提列表有序)
	包含:分解 + 合并
*/
func MergeSort(li []int, low, high int) {
	if low < high {
		mid := (low + high) / 2
		MergeSort(li, low, mid)
		MergeSort(li, mid + 1, high)
		Merge(li, low, mid, high)
	}
}

/**
Merge 归并
 */
func Merge(li []int, low, mid, high int) {
	i, j, lt, t := low, mid + 1, make([]int, len(li)), 0
	for i <= mid && j <= high { // 将结果拼接到新的数组
		if li[i] < li[j] {
			lt[t], i, t = li[i], i + 1, t + 1
		} else {
			lt[t], j, t = li[j], j + 1, t + 1
		}
	}

	for i <= mid {
		lt[t], i, t = li[i], i + 1, t + 1
	}
	for j <= high {
		lt[t], j, t = li[j], j + 1, t + 1
	}

	for i, j := low, 0 ; i <= high; i, j = i + 1, j + 1 { // 因为存在递归,将数值填回数组
		li[i] = lt[j]
	}
}
```

* **过程**

![并归排序](.\img\归并排序.gif)