一、归并排序
注意边界不要写错,写错一个边界就凉凉
思想:
1、将数组q由mid平分成两半,分别排序
2、先递归两边
比较i和j,如果i<j,将l[i]放入tmp后面,i++ ,如果i>j,将r[j]放入tmp后面,j++
如果其中一边递归完了,将另一边剩下的数都放入tmp中
3、归并,合而为一
最后for循环将tmp赋值给q,输出q
#include<iostream>
#include<cstdio>
using namespace std;
const int N = 1000010;
int n , q[N], tmp[N];//tmp[]是暂存数组
void merge_sort(int q[], int l, int r)
{
if (l >= r)//特殊情况,q数组中只有1个或0个数时
return;
int mid = l + r>>1; //mid=(l+r)/2
//递归排序两边
merge_sort(q, l, mid);
merge_sort(q, mid + 1, r);
int k = 0; //记录目前tmp中放了几个数
int i = l, j = mid + 1;
//当i、j都分别在它们的范围内时,将较小的数依次放入tmp数组后
while (i <= mid && j <= r)
{
if (q[i] <= q[j]) //左边的数较小
tmp[k++] = q[i++];
else
tmp[k++]= q[j++];
}
//记得当其中一边递归完了,将另一边剩下的数放到tmp后面
for(i=l,j=0;i<=r;i++,j++)
{
q[i]=tmp[j];
}
}
int main()
{
scanf_s("%d", &n);
for (int i = 0; i < n; i++)
{
scanf_s("%d", &q[i]);
}
merge_sort(q, 0, n - 1);
for (int i = 0; i < n; i++)
{
printf("%d ", q[i]);
}
return 0;
}
二、快排
思想:
1、先从数列中取出一个数作为基准数x
2、分区过程:将比基准数x大的数全放到x的右边,小于等于基准数x的数放到x的左边
3、再对左右区间重复步骤2,直到各区间只有一个数
#include<iostream>
#include<cstdio>
using namespace std;
const int N = 1000010;
int n, q[N];
void quick_sort(int q[], int l, int r)
{
if (l == r)//特殊情况
return;
//用左边界作为x,i和j先移动,再进行判断
//因此需要移动后的i和j是边界
int x = q[l];
int i = l - 1, j = r + 1;
while (i < j)
{
do i++; while (q[i] < x);
do j--; while (q[j] > x);
if (i < j)
swap(q[i], q[j]);
}
//递归处理左右两边
quick_sort(q, l, j);
quick_sort(q, j + 1, r);
}
int main()
{
scanf_s("%d", &n);
for (int i = 0; i < n; i++)
{
scanf_s("%d", &q[i]);
}
quick_sort(q, 0, n - 1);
for (int i = 0; i < n; i++)
{
printf("%d ", q[i]);
}
return 0;
}