排序算法原理
归并排序(Merge Sort)的原理简述如下:
(以升序为例)
1.利用分治的思想。将数组从中一分为二(称为左子数组、右子数组);
2.对左右子数组重复步骤1,直至划分为最小数组长度;
3.对划分后的子数组进行排序合并(两数组进行合并前,他们的上级合并数组已完成排序,因此合并时,依次对比两数组元素的大小,将较小值滚动存于临时数组中,即可合并完成);
4.对所有左右子数组逐级重复步骤3,待所有子数组合并完毕,排序完成。
代码示例
此处以c#代码为例,其他语言大同小异(转换为所需语言请看<语法说明>板块以作参考)
//归并排序
public static void MergeSort(int[] nums, int left, int right)
{
if (left >= right) return;
int mid = (left + right) / 2;
MergeSort(nums, left, mid);
MergeSort(nums, mid + 1, right);
Merge(nums, left, mid, right);
}
//合并左右子数组
private static void Merge(int[] nums, int left, int mid, int right
{
//声明临时数组,长度为左右子数组之和
int[] temp = new int[right - left + 1];
int i = left, j = mid + 1, k = 0;
//滚动对比两数组元素的大小,将较小值存于临时数组中
while (i <= mid && j <= right)
{
if (nums[i] <= nums[j])
temp[k++] = nums[i++];
else
temp[k++] = nums[j++];
}
//考虑到可能有剩余元素,直接放在临时数组尾部即可
while (i <= mid)
temp[k++] = nums[i++];
while (j <= right)
temp[k++] = nums[j++];
//将排序好的部分复制到原数组
for (k = 0; k < temp.Length; k++)
{
nums[left + k] = temp[k];
}
}
语法说明
为便于其他语言使用者进行代码转换,此处对可能存在的语法疑问作出注解。
1.public表示该函数是公开的,可根据具体语言及需求调整;
2.static表示该函数是静态的,可根据具体语言及需求调整;
3.void表示该函数返回值为空,可根据具体语言调整;
4.int是表示Int32类型的关键字,意为4个字节的有符号整形;
5.bool是表示Boolean类型的关键字,值为true或false;
6.for循环的语法结构为:
for(初始化索引;保持循环的条件;每次循环结束执行的语句){循环体}
这与C,C++,Java,Go,JS,TS,Dart类似。在Python,Swift,Rust中可替换为for index in range结构;
7.while循环的语法结构为:
while(保持循环的条件){循环体} 与其他语言类似,可进行简单替换;
8.方法名<T>的写法表示泛型,有些语言也称作参数多态或模板;
算法特性
时间复杂度O(n log n):划分子数组时,产生递归树高度为log n,合并时,每层操作数为n。
空间复杂度O(n):借助临时数组为辅助。