程序猿的第172天:N个正整数快速排序

Posted 程序猿每日一题

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了程序猿的第172天:N个正整数快速排序相关的知识,希望对你有一定的参考价值。


大家好,我们是既可以热热闹闹上蹿下跳,又可以安安静静编写代码的程序猿!


程序猿的第172天:N个正整数快速排序


让我们继续C++的操练,今天的题目是:


程序猿每日一题 (2018年6月2日)


Day 172  N个正整数快速排序


今天的题目和题解由编程爱好者小柯兄弟友情提供,感谢程序猿的第172天:N个正整数快速排序!


出题:


题目描述

对 n 个正整数从小到大排序


输入描述

输入共2行:

第一行一个正整数 n,表示数的个数;(n<100000)

第二行 n 个正整数,中间用空格隔开。


输出描述

输出一行,满足条件的序列,中间用空格隔开


样例输入

10

67 53 91 25 86 30 12 78 19 65


样例输出

12 19 25 30 53 65 67 78 86 91


回答:


分析:


以前学过的冒泡排序、选择排序等时间复杂度(读者可自行查阅关于时间复杂度的资料)都是O(n^2)级别的,对于n<100000的数据来说会超时,所以需要更快的排序方法——快速排序,它的时间复杂度为O(n*logn)。


这种排序的思路是:找一个数作为基准数(一般是第一个数),然后把当前序列中所有比基准数小的数都放到它的左边,比基准数大的数都放到它的右边。再分别递归排序基准数左边的序列和基准数右边的序列。


代码:


# include <bits/stdc++.h>

using namespace std;

const int MAXN=100000;

int n,a[MAXN];

void sort(int l,int r)//排[l,r)的序列

{

    if(r-l<=1) return;//边界条件:当前序列只有一个数

    int i=l,j=r-1,mid=a[l];//mid为基准数,i、j是排序时用的变量

    while(i<j)//当i和j没相遇时

    {

  while(i<j && a[j]>=mid) j--;//找到第一个比mid小的数

  if(i<j) a[i++]=a[j];//把这个数放到i的位置

  while(i<j && a[i]<=mid) i++;//找到第一个比mid大的数

  if(i<j) a[j--]=a[i];//把这个数放到j的位置

    }

    a[i]=mid;//把mid放到i和j相遇的位置

    sort(l,i);//排左子序列

    sort(i+1,r);//排右子序列

}


int main()

{

    cin>>n;

    for(int i=0;i<n;i++) cin>>a[i];

    sort(0,n);

    for(int i=0;i<n;i++) cout<<a[i]<<" ";

    cout<<endl;

    return 0;

}


本题还有另一种解法,就是调用算法库中的sort函数,代码要包含头文件# include <algorithm>。


# include <iostream>

# include <algorithm>

using namespace std;

int a[100000];

int main()

{

    cin>>n;

    for(int i=0;i<n;i++) cin>>a[i];

    sort(a,a+n);//终止点为a[n-1]

    for(int i=0;i<n;i++) cout<<a[i]<<" ";

    cout<<endl;

    return 0;

}


程序猿的第172天:N个正整数快速排序


欢迎有创意、有经验的你给我们回复更多其它代码方案!



当然,有空还可以复习一下前面的题目:


第156天:括号匹配





不过,话说回来,我们毕竟是调皮的猿猴类,万一某年某月某日忘了或懒得更新了,大家可以留言给我们,敲敲警钟或者表达下思念之情,都好啊!哈哈!好了,咱们明天见!


以上是关于程序猿的第172天:N个正整数快速排序的主要内容,如果未能解决你的问题,请参考以下文章

AcWing 107. 超快速排序(归并排序 + 逆序对)

快速选择算法

洛谷 1177 模板快速排序

洛谷 P1177 模板快速排序 快速排序/multiset排序

luogu 1177模板快速排序

第k个数(排序)