1. 程式人生 > 實用技巧 >C#資料結構與算法系列(二十三):歸併排序演演算法(MergeSort)

C#資料結構與算法系列(二十三):歸併排序演演算法(MergeSort)

1.介紹

歸併排序(MergeSort)是利用歸併的思想實現的排序方法,該演演算法採用經典的分治策略(分治法將問題分(divide)成一些小的問題然後遞迴求解,

而治(conquer)的階段則將分的階段得到的各答案“修補”在一起,即分而治之)

2.示意圖

說明:可以看到這種結構很像一顆完全二叉樹,可以採用遞迴和迴圈迭代的方式去實現,分階段可以理解為就是遞迴拆分子序列的過程

合併相鄰有序子序列

再來看看治階段,我們需要將兩個已經有序的子序列合併成一個有序序列,比如上圖中的最後一次合併,

要將[4,5,7,8]和[1,2,3,6]兩個已經有序的子序列,合併為最終序列[1,2,3,4,5,6,7,8],來看下實現步驟

3.例項

把陣列[8,4,5,7,1,3,6,2]使用歸併排序完成排序

    public class MergeSort
{
public static void Test()
{
int[] arr = { , , , , , , , }; int[] temp = new int[arr.Length]; Sort(arr,,arr.Length-,temp); Console.WriteLine(string.Join(",",arr));
} /// <summary>
/// 分+合方法
/// </summary>
/// <param name="arr"></param>
/// <param name="left"></param>
/// <param name="right"></param>
/// <param name="temp"></param>
private static void Sort(int[] arr,int left,int right,int[] temp)
{
if (left<right)
{
//中間索引
int mid = (left + right) / ; //向左遞迴進行分解
Sort(arr, left, mid, temp); //向右遞迴進行分解
Sort(arr, mid + , right, temp); //到合併
Merge(arr,left,mid,right,temp);
}
} /// <summary>
/// 合併方法
/// </summary>
/// <param name="arr">排序的原始陣列</param>
/// <param name="left">左邊有序序列的初始索引</param>
/// <param name="mid">中間索引</param>
/// <param name="right">右邊索引</param>
/// <param name="temp">做中轉陣列</param>
private static void Merge(int[] arr, int left, int mid, int right, int[] temp)
{
int i = left; //初始化i,左邊有序序列的初始化索引 int j = mid + ; //初始化j,右邊有序序列的初始化索引 int t = ; //指向temp陣列的當前索引 //(一)
//先把左右兩邊(有序)的資料按照規則填充到temp陣列
//直到左右兩邊的有序序列,有一邊處理完成為止
while (i <= mid && j <= right)
{
//如果左邊的有序序列的當前元素,小於或者等於右邊有序序列的當前元素
//即將左邊的當前元素,填充到temp陣列
//然後t++,i++
if (arr[i] <= arr[j])
{
temp[t] = arr[i]; t += ; i += ;
}
//反之,將右邊有序序列的當前元素,填充到temp陣列
else
{
temp[t] = arr[j]; t++; j++;
}
}
//(二)
//把有剩餘資料的一邊的資料依次全部填充到temp
while (i <= mid)
{
//左邊的有序序列還有剩餘的元素,就全部填充到temp
temp[t] = arr[i]; t++; i++;
} while (j <= right)
{
temp[t] = arr[j]; t++; j++;
}
//(三)
//將temp陣列的元素拷貝到arr,並不是每次都拷貝所有
t = ; int tempLeft = left; while (tempLeft <= right) //第一次合併 tempLeft=0,right=1 第二次 tempLeft=2 right=3;
{
arr[tempLeft] = temp[t]; t++; tempLeft++;
} }
}

結果圖