歸併排序

使用合併排序為一列數字進行排序的過程
歸併排序（Merge sort，或mergesort），是建立在歸併操作上的一種有效的排序算法，效率為（大O符號）。1945年由約翰·馮·諾伊曼首次提出。該算法是採用分治法（Divide and Conquer）的一個非常典型的應用，且各層分治遞歸可以同時進行。

**概述**
採用分治法:- 分割：遞歸地把當前序列平均分割成兩半。- 整合：在保持元素順序的同時將上一步得到的子序列整合到一起（歸併）。

**歸併操作**
歸併操作（merge），也叫歸併算法，指的是將兩個已經排序的序列合併成一個序列的操作。歸併排序算法依賴歸併操作。

**遞歸法（Top-down）**
#申請空間，使其大小為兩個已經排序序列之和，該空間用來存放合併後的序列
#設定兩個指針，最初位置分別為兩個已經排序序列的起始位置
#比較兩個指針所指向的元素，選擇相對小的元素放入到合併空間，並移動指針到下一位置
#重複步驟3直到某一指針到達序列尾
#將另一序列剩下的所有元素直接複製到合併序列尾

**迭代法（Bottom-up）**
原理如下（假設序列共有個元素）：
#將序列每相鄰兩個數字進行歸併操作，形成個序列，排序後每個序列包含兩/一個元素
#若此時序列數不是1個則將上述序列再次歸併，形成個序列，每個序列包含四/三個元素
#重複步驟2，直到所有元素排序完畢，即序列數為1

**實作範例**

**C語言**
迭代版：
int min(int x, int y) {
return x 
遞歸版：
// 分治-治
void mergeSort_conquer(int* array, int left, int mid, int right, int* temp) {
// left, mid和mid+1, right兩個有序數組
int i = left;
int j = mid + 1;
int index = 0;
while (i 

**C++**
迭代版：
template // 整數或浮點數皆可使用,若要使用物件(class)時必須設定"小於"(
遞歸版：
void Merge(vector &Array, int front, int mid, int end) {
// preconditions:
// Arrayfront...mid is sorted
// Arraymid+1 ... end is sorted
// Copy Arrayfront ... mid to LeftSubArray
// Copy Arraymid+1 ... end to RightSubArray
vector LeftSubArray(Array.begin() + front, Array.begin() + mid + 1);
vector RightSubArray(Array.begin() + mid + 1, Array.begin() + end + 1);
int idxLeft = 0, idxRight = 0;
LeftSubArray.insert(LeftSubArray.end(), numeric_limits::max());
RightSubArray.insert(RightSubArray.end(), numeric_limits::max());
// Pick min of LeftSubArrayidxLeft and RightSubArrayidxRight, and put into Arrayi
for (int i = front; i  &Array, int front, int end) {
if (front >= end)
return;
int mid = front + (end - front) / 2;
MergeSort(Array, front, mid);
MergeSort(Array, mid + 1, end);
Merge(Array, front, mid, end);
}

**C#**
public static List sort(List lst) {
if (lst.Count  left = new List();  // 定義左側List
List right = new List(); // 定義右側List
// 以下兩個循環把 lst 分為左右兩個 List
for (int i = 0; i 
/// 合併兩個已經排好序的List
/// 
/// 左側List
/// 右側List
/// 
static List merge(List left, List right) {
List temp = new List();
while (left.Count > 0 && right.Count > 0) {
if (left0  0) {
for (int i = 0; i  0) {
for (int i = 0; i 

**Ruby**
def merge list
return list if list.size 

**Java**
遞歸版：
static void merge_sort_recursive(int arr, int result, int start, int end) {
	if (start >= end)
		return;
	int len = end - start, mid = (len >> 1) + start;
	int start1 = start, end1 = mid;
	int start2 = mid + 1, end2 = end;
	merge_sort_recursive(arr, result, start1, end1);
	merge_sort_recursive(arr, result, start2, end2);
	int k = start;
	while (start1 
迭代版：
public static void merge_sort(int arr) {
	int orderedArr = new intarr.length;
	for (int i = 2; i = arr.length ? (arr.length - 1) : (left + i / 2);
			int right = i * (j + 1) - 1 >= arr.length ? (arr.length - 1) : (i * (j + 1) - 1);
			int start = left, l = left, m = mid;
			while (l 

**PHP**
function merge_sort($arr) {
	$len = count($arr);
	if ($len >1) + ($len & 1);
	$arr2d = array_chunk($arr, $half);
	$left = merge_sort($arr2d0);
	$right = merge_sort($arr2d1);
	while (count($left) && count($right))
		if ($left0 

**Python3**
def mergeSort(nums):
if len(nums) 

**Erlang**
%% @doc 歸併排序
g_sort() ->
;
g_sort(T) ->
T;
g_sort(L) ->
g_sort(L, length(L)).
g_sort( _ = L, Length) ->
SplitNum = trunc(Length / 2),
{L1, L2} = lists:split(SplitNum, L),
g_merge(g_sort(L1, SplitNum), g_sort(L2, Length - SplitNum));
g_sort(L, _Length) ->
L.
%% 已經排好序的兩個list合併
g_merge(, L2) ->
L2;
g_merge(L1, ) ->
L1;
g_merge( Rest1 = L1,  Rest2 = L2) ->
if
T1 =  g_merge(Rest1, L2);
true ->  g_merge(L1, Rest2)
end.

**Javascript**
遞歸法
function merge(left, right){
var result = ;
while(left.length > 0 && right.length > 0){
if(left0 迭代法

**Go**
package main
import (
	"fmt"
	"sort"
)
func MergeSort(list int) int {
	var length = len(list)
	if length 
遞歸版
package main
import (
	"fmt"
)
func merge(data int) int {
	sum := len(data)
	if sum = 2 {
		left = merge(left)
	}
	right := datasum/2:
	rSize := len(right)
	if rSize >= 2 {
		right = merge(right)
	}
	j := 0
	t := 0
	arr := make(int, sum)
	fmt.Println(left, right, data)
	for i := 0; i = lSize{
			arri = rightt
			t++
		}  else if t >= rSize{
			arri = leftj
			j++
		}
	}
	return arr
}
func main() {
	var aa = int{1000, 2, 31, 34, 5, 9, 7, 4, 6, 89, 90, 99, 99, 99, 99, 99}
	
	var bb = merge(aa)
	fmt.Println(bb)
}

**算法複雜度**
比較操作的次數介於和。
賦值操作的次數是。歸併算法的空間複雜度為：

**參考文獻**

**外部連結**
  Dictionary of Algorithms and Data Structures: Merge sort date=20050307155740 -  Merge sort Algorithm with example program date=20190520050043 -  Merge Sort Algorithm Simulation-  Mergesort For Linked Lists date=20050406031702 -  Mergesort in Java, Python, Perl, C, Ruby