歸併排序（，或），是建立在歸併操作上的一種有效的排序演算法，效率為 O nlog n （大 O 符號）。1945 年由約翰馮諾伊曼首次提出。該演算法是採用分治法（Divide and Conquer）的一個非常典型的應用，且各層分治遞迴可以同時進行。 概述 採用分治法 分割：遞迴地把當前序列平均分割成兩半。 整合：在保持元素順序的同時將上一步得到的子序列整合到一起（歸併）。 歸併操作 歸併操作（merge），也叫歸併演算法，指的是將兩個已經排序的序列合併成一個序列的操作。歸併排序演算法依賴歸併操作。 遞迴法（Topdown） 申請空間，使其大小為兩個已經排序序列之和，該空間用來存放合併後的序列 設定兩個指標，最初位置分別為兩個已經排序序列的起始位置 比較兩個指標所指向的元素，選擇相對小的元素放入到合併空間，並移動指標到下一位置 重複步驟 3 直到某一指標到達序列尾 將另一序列剩下的所有元素直接複製到合併序列尾 迭代法（Bottomup） 原理如下（假設序列共有 n 個元素）： 將序列每相鄰兩個數字進行歸併操作，形成 ceil n2 個序列，排序後每個序列包含兩 一個元素 若此時序列數不是 1 個則將上述序列再次歸併，形成 ceil n4 個序列，每個序列包含四 三個元素 重複步驟 2，直到所有元素排序完畢，即序列數為 1 實作範例 C 語言 迭代版： int min int x int y return x y x y void merge_sort int arr int len int a arr int b int malloc len sizeof int int seg start for seg 1 seg len seg seg for start 0 start len start seg 2 int low start mid min start seg len high min start seg 2 len int k low int start1 low end1 mid int start2 mid end2 high while start1 end1 start2 end2 b k a start1 a start2 a start1 a start2 while start1 end1 b k a start1 while start2 end2 b k a start2 int temp a a b b temp if a arr int i for i 0 i len i b i a i b a free b 遞迴版： 分治 治 void mergeSort_conquer int array int left int mid int right int temp left mid 和 mid1 right 兩個有序陣列 int i left int j mid 1 int index 0 while i mid j right if array i array j temp index array i else temp index array j 剩餘元素直接放入 temp while i mid temp index array i while j right temp index array j 放回原陣列 index 0 while left right array left temp index 分治 分 void mergeSort_divide int array int left int right int temp if left right int mid left right left 2 左邊歸併排序 mergeSort_divide array left mid temp 右邊歸併排序 mergeSort_divide array mid 1 right temp 合併兩個有序序列 mergeSort_conquer array left mid right temp void mergeSort int array int size int temp int malloc sizeof int size mergeSort_divide array 0 size 1 temp C 迭代版： templatetypename T 整數或浮點數皆可使用，若要使用物件 class 時必須設定 小於 的運運算元功能 void merge_sort T arr int len T a arr T b new T len for int seg 1 seg len seg seg for int start 0 start len start seg seg int low start mid min start seg len high min start seg seg len int k low int start1 low end1 mid int start2 mid end2 high while start1 end1 start2 end2 b k a start1 a start2 a start1 a start2 while start1 end1 b k a start1 while start2 end2 b k a start2 T temp a a b b temp if a arr for int i 0 i len i b i a i b a delete b 遞迴版： void Merge vectorint Array int front int mid int end preconditions Array frontmid is sorted Array mid1 end is sorted Copy Array front mid to LeftSubArray Copy Array mid1 end to RightSubArray vectorint LeftSubArray Arraybegin front Arraybegin mid 1 vectorint RightSubArray Arraybegin mid 1 Arraybegin end 1 int idxLeft 0 idxRight 0 LeftSubArrayinsert LeftSubArrayend numeric_limitsintmax RightSubArrayinsert RightSubArrayend numeric_limitsintmax Pick min of LeftSubArray idxLeft and RightSubArray idxRight and put into Array i for int i front i end i if LeftSubArray idxLeft RightSubArray idxRight Array i LeftSubArray idxLeft idxLeft else Array i RightSubArray idxRight idxRight void MergeSort vectorint 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 Listint sort Listint lst if lstCount 1 return lst int mid lstCount 2 Listint left new Listint 定義左側 List Listint right new Listint 定義右側 List 以下兩個迴圈把 lst 分為左右兩個 List for int i 0 i mid i leftAdd lst i for int j mid j lstCount j rightAdd lst j left sort left right sort right return merge left right summary 合併兩個已經排好序的 List summary param nameleft 左側 Listparam param nameright 右側 Listparam returnsreturns static Listint merge Listint left Listint right Listint temp new Listint while leftCount 0 rightCount 0 if left 0 right 0 tempAdd left 0 leftRemoveAt 0 else tempAdd right 0 rightRemoveAt 0 if leftCount 0 for int i 0 i leftCount i tempAdd left i if rightCount 0 for int i 0 i rightCount i tempAdd right i return temp Ruby def merge list return list if listsize 2 pivot listsize 2 Merge lambda left right final until leftempty or rightempty final if leftfirst rightfirst leftshift else rightshift end end final left right call merge list 0pivot merge list pivot1 end 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 end1 start2 end2 result k arr start1 arr start2 arr start1 arr start2 while start1 end1 result k arr start1 while start2 end2 result k arr start2 for k start k end k arr k result k public static void merge_sort int arr int len arrlength int result new int len merge_sort_recursive arr result 0 len 1 迭代版： public static void merge_sort int arr int orderedArr new int arrlength for int i 2 i arrlength 2 i 2 for int j 0 j arrlength i 1 i j int left i j int mid left i 2 arrlength arrlength 1 left i 2 int right i j 1 1 arrlength arrlength 1 i j 1 1 int start left l left m mid while l mid m right if arr l arr m orderedArr start arr l else orderedArr start arr m while l mid orderedArr start arr l while m right orderedArr start arr m Systemarraycopy orderedArr left arr left right left 1 PHP function merge_sort arr len count arr if len 1 return arr half len1 len 1 arr2d array_chunk arr half left merge_sort arr2d 0 right merge_sort arr2d 1 while count left count right if left 0 right 0 reg array_shift left else reg array_shift right return array_merge reg left right arr array 21 34 3 32 82 55 89 50 37 5 64 35 9 70 arr merge_sort arr for i 0 i count arr i echo arr i Python3 def mergeSort nums if len nums 2 return nums mid len nums 2 left mergeSort nums mid right mergeSort nums mid i j 0 result while i len left and j len right if left i right j resultappend left i i 1 else resultappend right j j 1 while i len left resultappend left i i 1 while j len right resultappend right j j 1 return result if __name__ __main__ nums 1 4 2 36 1 0 25 34 8 9 1 0 print original nums print Sorted mergeSort 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 listssplit 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 T1 Rest1 L1 T2 Rest2 L2 if T1 T2 T1 g_merge Rest1 L2 true T2 g_merge L1 Rest2 end Javascript 遞迴法 function merge left rightvar result while leftlength 0 rightlength 0if left 0 right 0resultpush leftshift else resultpush rightshift return resultconcat left right function mergeSort arrif arrlength 1 return arr var middle Mathfloor arrlength 2 var left arrslice 0 middle var right arrslice middle return merge mergeSort left mergeSort right 迭代法 Go package main import fmt sort func MergeSort list int int var length len list if length 2 return list var mid length 2 return merge MergeSort list mid MergeSort list mid func merge x y int int var r int make int len xlen y for i j 0 0 if i len x j len y x i y j r ij x i i else if j len y r ij y j j else break return r func main var list int int 56 48 58 94 87 4 5 61 5 8 74 9 84 15 94 9 4 31 41 68 7 4 6 94 16 9 8 4 fmtPrintln MergeSort list fmtPrintln list sortInts list fmtPrintln list 遞迴版 package main import fmt func merge data int int sum len data if sum 1 return data left data 0 sum2 lSize len left if lSize 2 left merge left right data sum2 rSize len right if rSize 2 right merge right j 0 t 0 arr make int sum fmtPrintln left right data for i 0 i sum i if j lSize t rSize if left j right t arr i left j j else arr i right t t else if j lSize arr i right t t else if t rSize arr i left j 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 fmtPrintln bb 演算法複雜度 比較操作的次數介於 nlog n2 和 nlog n n 1。 賦值操作的次數是 2nlog n。歸併演算法的空間複雜度為： Theta n 參考文獻 外部連結 Dictionary of Algorithms and Data Structures Merge sort Merge sort Algorithm with example program Merge Sort Algorithm Simulation Mergesort For Linked Lists Mergesort in Java Python Perl C Ruby Category 排序演算法 Category 帶有程式碼示例的條目 noSorteringsalgoritmeFlettesortering