算法:合並排序(Merge Sort)


算法定義

合並排序是一種遞歸算法,思路如下:

  • 如果源數組長度為 1,立即返回。
  • 將源數組平分為兩個新數組:Left 和 Right。
  • 對 Left 執行遞歸排序。
  • 對 Right 執行遞歸排序。
  • 將排序后的 Left 和 Right 執行合並到原數組。

可以看出來,改算法的重點是已排序數組的合並過程。

算法舉例

【5,4,3,2,1】

【5,4,3】【2,1】

【5,4】【3】【2,1】

【5】【4】【3】【2,1】

【4,5】【3】【2,1】

【3,4,5】【2,1】

【3,4,5】【2】【1】

【3,4,5】【1,2】

【1,2,3,4,5】

算法實現

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 
 7 namespace DataStuctureStudy.Sorts
 8 {
 9     class MergeSort<T>
10         where T : IComparable<T>
11     {
12         private static void Swap(T[] items, int left, int right)
13         {
14             if (left != right)
15             {
16                 var temp = items[left];
17                 items[left] = items[right];
18                 items[right] = temp;
19             }
20         }
21 
22         public static void Sort(T[] items)
23         {
24             if (items.Length < 2)
25             {
26                 return;
27             }
28 
29             int leftSize = items.Length / 2;
30             int rightSize = items.Length - leftSize;
31 
32             T[] left = new T[leftSize];
33             T[] right = new T[rightSize];
34 
35             Array.Copy(items, 0, left, 0, leftSize);
36             Array.Copy(items, leftSize, right, 0, rightSize);
37 
38             Sort(left);
39             Sort(right);
40             Merge(items, left, right);
41         }
42 
43         private static void Merge(T[] items, T[] left, T[] right)
44         {
45             var leftIndex = 0;
46             var rightIndex = 0;
47 
48             for (var i = 0; i < items.Length; i++)
49             {
50                 if (leftIndex >= left.Length)
51                 {
52                     items[i] = right[rightIndex];
53                     rightIndex++;
54                 }
55                 else if (rightIndex >= right.Length)
56                 {
57                     items[i] = left[leftIndex];
58                     leftIndex++;
59                 }
60                 else if (left[leftIndex].CompareTo(right[rightIndex]) < 0)
61                 {
62                     items[i] = left[leftIndex];
63                     leftIndex++;
64                 }
65                 else
66                 {
67                     items[i] = right[rightIndex];
68                     rightIndex++;
69                 }
70             }
71         }
72     }
73 }

合並過程

已排序數組的合並過程比較有意思,分別對 Left 和 Right 維護一個從左到右的指針,分別是:leftIndex 和 RightIndex,當填充目標數組的第 i 個元素時,需要從 Left 和 Right 中找到剩余元素(指針到末尾部分的元素)的最小值,因為是已排序數組,只需比較 Left[LeftIndex] 和 Right[RightIndex] 的大小,將最小的元素填充到目標數組的第 i 個位置即可,然后相應的指針加 1。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM