归并排序:
分治法:将已有序的子序列合并,得到完全有序的序列。
即先使每个子序列有序,再使子序列段间有序。
1、分离
将已有数列不断分离成两段长度基本相同(当已有数列长度是奇数时,则一半长一半短),直到分离成长度为 1 的 n 个数列(也就是n个数)。
2、合并
将数列两两合并,每次合并时进行排序,直到完成排序。
Code:
//a为起始未排序的数组,b为辅助数组
int n, a[12000], b[12000];
//合并
void merge(int left, int mid, int right)
{
//i为第一组数的起始位置,j为第二组数的起始位置
//k为辅助数组的起始位置
int i = left, j = mid+1 , k = left;
//前提:两组数中同时有数没放完 对两组数进行合并,同时排序
while (i <= mid && j <= right)
{
if (a[i] <= a[j])
{
b[k++] = a[i++];
}
else
{
b[k++] = a[j++];
}
}
//到此为止,至少有一组数已经放完了,但是为了确保把所有的数都放完,再检查一遍
while (i <= mid)
{
b[k++] = a[i++];
}
while (j <= right)
{
b[k++] = a[j++];
}
//把当前b中的所有元素复制到a中,把b腾空,下次还要继续用
for (int i = left; i <= right; i++)
{
a[i] = b[i];
}
}
//分离
void mergesort(int left, int right)
{
if (left >= right) return;//left和right相遇,说明已经分离完了,直接return
int mid = (left + right) / 2;//用中间数把序列分为左右两部分
mergesort(left, mid);//继续分离左边序列
mergesort(mid + 1, right);//继续分离右边序列
//分离完进行合并
merge(left, mid, right);
}
//测试函数
int main()
{
cin >> n;
for (int i = 0; i < n; i++)
{
cin >> a[i];
}
mergesort(0, n - 1);
for (int i=0;i
时间复杂度:O(nlogn)
空间复杂度:O(n)
稳定性:稳定