本期介绍下两种基础算法的写法与区别,希望对您有些许帮助。
一.快排:
快排的排序方法是先排再分开,如此循环往复排出来正确顺序。
大体方式是一个数组,两个端点,两个下标,我们随机选取一个数为标准值,让两个下标分别从两头出发,之后遇到与大于(或小于)x的数就停下,两边都停下的话就交换数,之后会以x为界限形成左右两边要么都大于或都小于x的数组,然后继续分。
那么我们可以通过一个递归程序实现,递归中程序如下:
void quick_sort(int q[], int l, int r){//快排模板,l左边固定端点,r右边固定端点
if(l>=r) return;//如果左右两端点重合就结束
int x=q[(l+r)>>1], i=l-1, j=r+1;//随便规定一个x值来以他为大小界限,i和j(移动端点)先都在l和r的外侧
while(i<j){//当i,j未重合,就移动
do i++; while(q[i]<x);//先执行移动操作,再进行比较:如果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);
}
快排中的x是可以随意规定的,但是有时候处理不好会陷入死循环,所以给大家一个模板仅供参考。
完整代码如下:
#include <iostream>
using namespace std;
const int M = 1e6+7;
int n, q[M];
void quick_sort(int q[], int l, int r){//快排模板,l左边固定端点,r右边固定端点
if(l>=r) return;//如果左右两端点重合就结束
int x=q[(l+r)>>1], i=l-1, j=r+1;//随便规定一个x值来以他为大小界限,i和j(移动端点)先都在l和r的外侧
while(i<j){//当i,j未重合,就移动
do i++; while(q[i]<x);//先执行移动操作,再进行比较:如果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("%d",&n);
for(int i=1; i<=n; i++) scanf("%d",&q[i]);
quick_sort(q,1,n);
for(int i=1; i<=n; i++) printf("%d ",q[i]);
return 0;
}
二.归并:
归并排序与快速排序有所不同,归并排序是先将原数组分开变为一个个小数组,之后经过递归程序在将排好的数组重新填回原数组。
具体实现:先将数组分开,分开之后会形成两个数组,为这两个数组规定两个下标,让下标所对应的数进行比较,哪一边数小就将那个数填入新数组,并且下标向前移动。而另一个数组的下标不动,最后会出现有一边的数组下标没走完,则这时候需要将剩下的数填入新数组就可以(因为这些数组中的数的排序是通过最小的数组合并出来的,所以顺序都是由小到大,直接填入新数组就可以),然后这时将新数组中的数覆盖掉原数组中对应的位置的数即可,代码如下:
#include <iostream>
using namespace std;
const int M =1e6+7;
int n;
int q[M],tmp[M];
void merge_sort(int q[], int l, int r){//归并模板:l左端点,r右端点
if(l>=r) return;//如果左右端点重合就结束
int mid=l+r>>1;
merge_sort(q,l,mid); merge_sort(q,mid+1,r);//归并就是先把所有数分开在合并,所以先分开数
int k=1, i=l,j=mid+1;//分完后一个新数组tmp代表排完序的数组,i是左边分出来数组的下标,j是右边的下标(可移动)
while(i<=mid&&j<=r) {//mid和r就分别是左右两个数组的尾端点
if(q[i]<=q[j]) tmp[k++]=q[i++];//去比较左右两个数组中的数,哪个小就先进tmp数组,然后下标往后走继续比较
else tmp[k++]=q[j++];
}
while(i<=mid) tmp[k++]=q[i++];//如果哪边下标走完了就看另一个数组,让其剩下的数排进tmp
while(j<=r) tmp[k++]=q[j++];
for(int i=l, j=1; i<=r; i++, j++) q[i]=tmp[j];//然后将这一段的tmp数组返回给这一段的q数组就可
}
int main(){
scanf("%d", &n);
for(int i=1; i<=n; i++) scanf("%d", &q[i]);
merge_sort(q,1,n);
for(int i=1; i<=n; i++) printf("%d ",q[i]);
return 0;
}