首先给出一个序列,假设这时候要求你对他按照从小到大的顺序进行排列,那么有一种排序方法-即快速排序,它包含了分治、二分、递归思想的运用,对序列进行排序并大大降低了时间复杂度,
上代码:
#include<iostream>
using namespace std;
int a[5000001],n;//定义a数组用来存储需要排序的所有数字,n代表数字总个数
void quicksort(int left,int right){
int i,j,t,temp;
if(left>right)
return;
temp=a[left];//temp就是存储的基准数
i=left;
j=right;
while(i!=j){
//需先从右往左找
while(a[j]>=temp && i<j)
j--;
//然后从左往右找
while(a[i]<=temp && i<j)
i++;
//交换两个数在数组中的位置
if(i<j){
t=a[i];
a[i]=a[j];
a[j]=t;
}
}
//然后将基准数归位
a[left]=a[i];
a[i]=temp;
quicksort(left,i-1);//用递归的思想,继续处理左边
quicksort(i+1,right);//同理处理右边
return;
}
int main(){
int i,j;
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
quicksort(1,n);
for(int i=1;i<=n;i++)
cout<<a[i]<<' ';
//暂停程序以便于查看程序输出的内容
getchar();
getchar();
return 0;
}
做一个简单的总结,首先我们得到一个输入完成的序列,假设它的下标是从1到n,那么1,n分别对应左边界和有边界,需要注意的是我们需要考虑边界问题,所以当left大于right的时候就直接返回函数类型即可,我们可以看出由于快速排序是利用分治的思想,二分和递归的方法对一个序列进行排序,每次我们需要确定一个基准数,并把这个基准数放在序列中的某一位置,并且满足在此位置左边的数全部都小于基准数,右边的数字都大于这一个基准数,在不断一半一半的分割序列之后,最后分割成只有一个数字的时候,递归就得以结束,这时候序列中的所有值都完成了目标排序。
同样如果想要按照从大到小对输入的序列进行排序的话可以这么改:
#include<iostream>
using namespace std;
int a[5000001],n;//定义a数组用来存储需要排序的所有数字,n代表数字总个数
void quicksort(int left,int right){
int i,j,t,temp;
if(left>right)
return;
temp=a[left];//temp就是存储的基准数
i=left;
j=right;
while(i!=j){
//需先从右往左找
while(a[j]<=temp && i<j)
j--;
//然后从左往右找
while(a[i]>=temp && i<j)
i++;
//交换两个数在数组中的位置
if(i<j){
t=a[i];
a[i]=a[j];
a[j]=t;
}
}
//然后将基准数归位
a[left]=a[i];
a[i]=temp;
quicksort(left,i-1);//用递归的思想,继续处理左边
quicksort(i+1,right);//同理处理右边
return;
}
int main(){
int i,j;
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
quicksort(1,n);
for(int i=1;i<=n;i++)
cout<<a[i]<<' ';
//暂停程序以便于查看程序输出的内容
getchar();
getchar();
return 0;
}
其实会发现只是取反了函数里面while的两个符号而已。
需要注意的是快排在最坏的情况之下(相邻的两个数进行交换),它的时间复杂度和冒泡排序是一样的,快速排序是基于二分的思想实行的,大多数情况下快排都比冒泡排序快是因为快排的交换是跳跃式的而不像冒泡是一个个的挨着去对比,快排的每次操作都会将基准数放在对应的位置,使得他左边的数字都小于他,右边的数字都大于他(或者左边都大于他右边都小于他)。
下面是我在做题的过程中发现的知识:
在强大的STL库中存在一个神奇的函数,那就是nth_element,这个函数主要用来将数组元素中第k小的整数排出来并在数组中就位,随时调用,可谓十分实用。
函数语句:nth_element(数组名,数组名+第k小元素,数组名+元素个数),题目如下:
代码如下:
#include<bits/stdc++.h>
using namespace std;
long long n,k,a[5000010];
int main()
{
scanf("%d%d",&n,&k);
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
nth_element(a,a+k,a+n);//使第k小整数就位
printf("%d",a[k]);//调用第k小整数
}