题目描述:
给定N个(长整型范围内的)整数,要求输出从小到大排序后的结果。
本题旨在测试各种不同的排序算法在各种数据情况下的表现。各组测试数据特点如下:
数据1:只有1个元素;
数据2:11个不相同的整数,测试基本正确性;
数据3:10^3个随机整数;
数据4:10^4个随机整数;
数据5:10^5个随机整数;
数据6:10^5个顺序整数;
数据7:10^5个逆序整数;
数据8:10^5个基本有序的整数;
数据9:10^5个随机正整数,每个数字不超过1000。
输入格式:
输入第一行给出正整数N(≤10^5 ),随后一行给出N个(长整型范围内的)整数,其间以空格分隔。
输出格式:
在一行中输出从小到大排序后的结果,数字间以1个空格分隔,行末不得有多余空格。
输入样例:
11
4 981 10 -17 0 -20 29 50 8 43 -5
输出样例:
-20 -17 -5 0 4 8 10 29 43 50 981
解题思路:
看到10^5后,孩子脑子里只剩下快排了。不要问为什么……想想空间,想想时间。
首先,咱们说说快排的思想:通过一次排序,将要排序的数据分割成两个部分,其中一部分的数据比另一部分的数据都要大。然后再按次方法对这两部分数据分别进行快速排序,然后进行递归,从而使整个数据变成有序数列。
可能这样说大家有点不明白哈!下面给大家文字详解一下。。。。
- 首先我们要选一个数据作为参考数,将大于它的放右边,小于它的放左边。(一般是指定第一个元素)
- 然后设置两个变量 i,j 。 i 为第一个元素的下标,j 为最后一个元素的下标。
- 然后用变量 t 记录下第一个元素,及 t=a[0] 。
- 接着 j 往前扫描,每次 j 都产生自减。直到找到一个小于 t 的值,然后两者进行互换。
- 当然 i 往后扫描,每次 i 都产生自加。直到找到一个大于 t 的值,然后两者进行互换。每次换完后要记得break终止哦!!!!
- 然后便进入一个大循环重复以上操作,直到 i > j 后,便算完成一次排序啦!!
咳咳,接下来按照题目给的输入输出,给大家跑一趟:
接着 j 与 t 进行比较,发现 -5 小于 4 ,所以直接将 -5 扔前面去,然后终止。 i 与 t 进行比较, -5 不大于 4 ,所有往右走,发现 981 大于 4 ,所以将 981 扔后面去。一次内部小循环运行完后,将 t 归位。及 a[i]=t 。
然后重复此操作,一直比较到 i 不再小于 j 时 便算完成一次快速排序。
接下就便是对余下的部分进行分开递归。最终使数列达到有序。
刚刚开始打完的时候感觉太复杂了,经过反复的优化,感觉这应该是最好记忆滴啦!
这浓浓的对称美。。。。啊哈哈哈哈哈
总的来说,快速算法还是很重要的,大家最好还是能够背下来,以防不时之需。
话不多说,代码奉上:
#include<stdio.h>
int fun(int a[],int n)
{
int i,j,t;
i=0; //记录第一个元素的下标
j=n-1; //记录最后一个元素的下标
if(n<=0)return 0;
t=a[0]; //拍照技术,被压了以后好复原,也是作为标准数
while(i<j)
{
while(i<j)
{
if(t>a[j]){a[i]=a[j];break;}
j--; //j不停的往前扫描
}
while(i<j)
{
if(t<a[i]){a[j]=a[i];break;}
i++; //i不停的往后扫描
}
a[i]=t;
}
fun(a,i); //对前半部分进行递归
fun(a+i+1,n-i-1); //对后半部分进行递归
}
int main()
{
int a[101100],n,i;
scanf("%d",&n);
for(i=0;i<n;i++)scanf("%d",&a[i]);
fun(a,n);
for(i=0;i<n;i++)
{
printf("%d",a[i]);
if(i+1!=n)printf(" ");
}
return 0;
}