题外话: 哦豁,一天肝4章,可以啊你小子
1.什么是归并排序
- 将两个或两个以上的有序子序列,归并为一个有序序列。
- 你可以理解为, 初中的时候上手工课,老师说2个同学一组;
- 我们每2个人作为一个组合,选出一个最佳作品;
- 然后老师又说:每两个组合合并为一个4人组合,再选出一个最佳作品;
- 再来,每两个组合再次合并为一个8人组合,直到选出一个最优秀的作品。
PS: 上面的例子并不严谨,只是让你了解“合并”这个过程。
2. 2-路归并排序
- 什么是2-路归并排序?
- 上面说到,归并排序是“2个或2个以上的序列xxxxx”;
- 那么我们只选择2个序列2个序列合并,那么就是2-路归并排序。
- 图片解释
3. 2-路归并排序代码实现
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace YoyoCode
{
internal class MSort
{
//辅助数组
static int[] sArray;
/// <summary>
/// 归并排序
/// </summary>
/// <param name="pArray">需要排序的数组</param>
public static void MergeSort(int[] pArray)
{
//辅助数组的初始化
sArray = new int[pArray.Length];
//步长限制1、2、4、8、16...
//如果数组长度为9,最大步长不能为4,必须是8
//因为8和剩下的一个元素需要合并
for (int step = 1; step < pArray.Length; step *= 2)
{
//在步长限制下,对数组的两两归并
for (int j = 0; j < pArray.Length - step; j += step + step)
{
Merge(pArray, j, j + step - 1, Math.Min(j + step + step - 1, pArray.Length - 1));
}
}
}
/// <summary>
/// 对两个子数组进行排序
/// </summary>
/// <param name="pArray">数组</param>
/// <param name="low">子数组1的起始index</param>
/// <param name="mid">子数组1的终止index,mid+1就是子数组2的起始index</param>
/// <param name="high">子数组2的终止index</param>
private static void Merge(int[] pArray, int low, int mid, int high)
{
//辅助数组赋值
for (int k = low; k <= high; k++)
{
sArray[k] = pArray[k];
}
//合并
int i = low;
int j = mid + 1;
for (int k = low; k <= high; k++)
{
//越界直接合并
if (i > mid)
{
pArray[k] = sArray[j++];
}
else if (j > high)
{
pArray[k] = sArray[i++];
}
else
{
//没越界则比较,两者中小的放进结果中
if (sArray[i] < sArray[j])
{
pArray[k] = sArray[i++];
}
else
{
pArray[k] = sArray[j++];
}
}
}
}
}
}
说明: 都在酒里,啊不是,都在注释里了,看注释读一遍,再跟着手搓一边就明白原理了,看着恶心而已~
4.算法分析
- 时间复杂度
- O(nlogn)
- 空间复杂度
- O(n)
- 算法稳定性
- 稳定
结束语: 好累呀好累呀好累呀