Description
给定N(N≤10^5)个整数,要求用快速排序对数据进行升序排列,注意不得使用STL。
Input
输入数据第一行给出正整数N(≤10^5),随后给出N个整数,数字间以空格分隔。
Output
输出排序后的结果,数字间以一个空格间隔,行末不得有多余空格。
Sample
Input
8
49 38 65 97 76 13 27 49
Output
13 27 38 49 49 65 76 97
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <math.h>
using namespace std;
int a[100001];
void qst(int a[],int l,int r)
{
//key随便定义吗?
//答:定义一个变量,规定第一个值为标杆值,当然此值一般可以随便选择。
int key=a[l];
//为什么用i和j?
//答:来确定新的右边界和左边界,传进来的l和r是下次递归调用的左边界,和右边界,所以不能直接用l,和r参与循环。(可以看最后递归的两句)。
int i=l,j=r;
//为什么边界是l>r?
//l,和r是对本次递归来说的,传进来的参数是l和r,传进来的相等就代表已经不可再分一半递归了。
if(l>=r)
{
return;
}
//外层大循环什么意思?
//利用i和j,来确定此次循环从左边i开始进行i++,和右边j同时开始j--,保证最后全部移动完毕
while(i<j)
{
//下面第一个小循环的作用?
//这个循环是让满足条件的快速移动过去-
//例如 key=3
//序列是3,2,3,1,4,5,2,4,j指向4的时候会满足while,j--,这时候j指向2不满足while,跳出循环。
//循环的是哪几句?
//答:循环的 { j--;}仅仅这一句,只要满足a[j]>=key,就说明右边的这个值,是大于标杆的,已经在右边了,不用把他移动。
//为什么还要保证i<j?
//答:因为右边的j如果一直j--,会出错的,所以同时保证i<j
while(i<j&&a[j]>=key)
{ j--;}
//为什么是 a[i]=a[j],不是a[j]=a[i]?
//当上面的循环不满足时,代表需要移动,把a[i]=a[j],不会造成覆盖问题丢失被赋值的数,因为a[i]已经被key保存下来,循环结束,会把key放到i==j的中间位置。
a[i]=a[j];
while(i<j&&a[i]<=key)//同上
i++;
a[j]=a[i];
}
a[i]=key;//中间位置是没有值的,把key值放到中间,标杆就到了中间?
qst(a,l,i-1);//连续递归调用函数,左边界为传进来的,右边界是我们用i,j刚确定的。
qst(a,i+1,r);
}
int main()
{
int n;
cin>>n;
for(int i=1; i<=n; i++)
{
scanf("%d",&a[i]);
}
qst(a,1,n);
for(int i=1; i<=n; i++)
{
printf("%d ",a[i]);
}
return 0;
}
去注释版
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <math.h>
using namespace std;
int a[100001];
void qst(int a[],int l,int r)
{
int key=a[l];
int i=l,j=r;
if(l>=r)
{
return;
}
while(i<j)
{
while(i<j&&a[j]>=key)
{ j--;}
a[i]=a[j];
while(i<j&&a[i]<=key)//同上
i++;
a[j]=a[i];
}
a[i]=key;
qst(a,l,i-1);
qst(a,i+1,r);
}
int main()
{
int n;
cin>>n;
for(int i=1; i<=n; i++)
{
scanf("%d",&a[i]);
}
qst(a,1,n);
for(int i=1; i<=n; i++)
{
printf("%d ",a[i]);
}
return 0;
}