通过递归的方式将大的数组一直分割,直到数组的大小为 1,此时只有一个元素,那么该数组就是有序的了,之后再把两个数组大小为1的合并成一个大小为2的,再把两个大小为2的合并成4的 … 直到全部小的数组合并起来。
整体的思想是分治,即先使每个子序列有序,再使子序列段间有序
将数组元素拆分成个体,然后两两合并成一组,以此类推
递归注意结束条件、递归公式
先递归,再合并
1.完成数组拆分,直到拆成单个元素
2.完成两个分别有序子序列合并得功能函数
#include<iostream>
using namespace std;
#include<vector>
//这里借助一个临时数组来避免递归过程中每次复制回去的操作
//左闭右闭
void merge_sort(vector<int>& nums,vector<int>& temp,int left,int right)
{
//递归结束条件 只有一个元素了
if (left >= right) return;
int mid = (left + right) >> 1;
int low1 = left, high1 = mid;
int low2 = mid + 1, high2 = right;
//每次二分
merge_sort(nums, temp, low1, high1);
merge_sort(nums, temp, low2, high2);
//合并两个有序数组 (left,mid) (mid+1,right)
int index = low1;//temp数组下标索引
//依次比较两个序列 有一个索引会先超出范围导致循环退出
while (low1 <= high1 && low2 <= high2)
{
temp[index++] = nums[low1] < nums[low2] ? nums[low1++] : nums[low2++];
}
//如果还有一个有序数组是还有剩余的直接放到temp的后面
while (low1 <= high1)
{
temp[index++] = nums[low1++];
}
while (low2 <= high2)
{
temp[index++] = nums[low2++];
}
//将临时数组中的元素拷贝回去
for (int i = left; i <= right; i++)
{
nums[i] = temp[i];
}
}
int main()
{
vector<int> nums = { 1,9,3,0,2,2,6,7,0 };
vector<int> temp;
temp.resize(nums.size());
merge_sort(nums, temp, 0, nums.size() - 1);
for (int i = 0; i < nums.size(); i++)
{
cout << nums[i] << " ";
}
}
时间复杂度分析
拆分不怎么耗时可以忽略
主要复杂度在是有序数组合并
每y一层合并都要遍历所有的数字一次 O(n)
总共要搞logN层
所以总共复杂度为nlogn
空间复杂度
用到了一个temp o(n)
稳定性
不涉及到元素交换
是稳定的