分治法
大问题拆分成小问题,有共同的解决办法,小问题解决完合并后大问题就迎刃而解
归并排序
归并的名字就是先分,又合并,合并完排序
很稳定
把数组分成两部分,两部分分成四部分,四部分分成八部分
每一部分就剩两个了,进行排序调换
两个部分在合并,排序调换
两个部分(四个部分)在合并,排序调换
#include<stdio.h>
const int N = 1e6 + 1;
int q[N],temp[N];//原数组,预留数组
void merge_sort(int q[], int l, int r)
{
if (l >= r) //回溯
return;
int mid = (l + r) / 2,i=l,j=mid+1,k=0; //二分
merge_sort(q, l, mid);//对中点左区间排序 //第一层回溯完l=mid //回溯完是排好序的左区间
merge_sort(q, mid+1,r);//对中点右区间排序 //第一层回溯完mid+1=r //回溯完是排好序的左区间
while (i <= mid && j <= r)//第一层回溯 i=mid-1,j=r
{
if (q[i] >= q[j]) //存小的
temp[k++] = q[j++];
else
temp[k++] = q[i++];
}
while (i <= mid) temp[k++] = q[i++];//没存完的继续存
while (j <= r) temp[k++] = q[j++];//没存完的继续存
for (i = l, j = 0; i <= r; i++, j++) q[i] = temp[j]; //存完的还回去
}
int main()
{
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++) scanf("%d", &q[i]);
merge_sort(q, 0, n - 1);
for (int i = 0; i < n; i++) printf("%d ", q[i]);
}
快速排序
不需要合并了,是拆分,排好序后分。速度很快就叫快速排序
但是不稳定又好用
不是以中点分了,随便找个点分,这个点叫基点,分好后左边是小于这个点的,右边是大于这个点的,如果不是,就左右的两个不符合的点调换,类似于双指针
先找好基点,大小放好后,在进行分
分的时候还是左右区间,每个区间在按照基点左小右大换,换完分,到最后就是全部都能左小右大了
#include<stdio.h>
const int N = 1e6 + 10;
int n;
int q[N];
void swap(int *a, int *b) //交换
{
int t;
t = *a;
*a = *b;
*b = t;
}
void quick_sort(int q[], int l, int r)
{
if (l >= r)//回溯
return;
int x = q[l], i = l - 1, j = r + 1;//以左边界为基点
while (i < j)//重合退出循环
{
do i++; while (q[i] < x);//i,比基点小就向右移动
do j--; while (q[j] > x);//j,比基点大就向左移动
if (i < j) //i移动到大于基点的位置,不符合要求,j同理,所以互换
swap(&q[i], &q[j]); //交换二者
}//在基点的左右两端达到左小右大
quick_sort(q, l, j);//j,i相当于基点的位置,对基点的左区间在继续排序
quick_sort(q, j + 1, r);//对基点的右区间在继续排序
}
int main()
{
scanf("%d", &n);
for (int i = 0; i < n; i++) scanf("%d", &q[i]);
quick_sort(q, 0, n-1);
for (int i = 0; i < n; i++) printf("%d ", q[i]);
printf("\n");
return 0;
}
小萌新一枚~多多指正呀~