上次我们分享了一个基本排序方法———冒泡排序的使用,今天我们来分享第二种排序方法:
快速排序
快速排序,我们简称快排。我们先来回顾一下上次的冒泡排序,冒泡排序就是在一个序列里,两两比较并根据大小关系进行换位处理,经过多次从头到尾的比较,从而实现整个序列的排序。这个排序方法可行,并且好像并没有什么局限性,那为什么我们还需要快速排序?那是因为冒泡排序在时间上很耗时,也就是他的时间复杂度很大。我们知道,程序最重要的一个因素就是运行时间,时间极其重要,相信大家也在日常刷题的时候,遇到“时间超限”的报错。
把我们来看一下冒泡排序,他的时间复杂度是O(N^2)假如我 们的计算机每秒钟可以运行 10 亿次,那么对 1 亿个数进行排序,冒泡排序则需要 1 千万秒,达到 115 天之久,是不是很吓人?
所以,为了解决时间问题,我们就有了快速排序,顾名思义,快速排序是一种效率很高的排序方法,让我们一起来康康。
首先我们通过实例来分析快速排序的原理。
![](https://i-blog.csdnimg.cn/blog_migrate/e5c4afe3d900ffc98599ec3fd5d3c2c1.png)
![](https://i-blog.csdnimg.cn/blog_migrate/3f7c8d7147c4bc86f632910ec1750dcd.png)
然后我们剩下的也是这么操作,就可以实现我们所需要的了。只是需要注意一点:
到最后 i 和 j 相遇之后,即在本实例中的 3 的位置,因为我们要把基准数放在中间,所以最后要实现3和6的交换哦
那么根据这个思想,当以6位基准数完成一次排序之后,我们就可以在6的左边和右边分别找基准数,在两边分别进行快速排序,最后就可以完成对整个序列的排序。
整个过程图示:
#include <stdio.h>
int a[101],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)//当哨兵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);//继续处理右边的,这里是一个递归的过程
}
int main()
{
int i,j,t;
//读入数据
scanf("%d",&n);
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
quicksort(1,n); //快速排序调用
//输出排序后的结果
for(i=1;i<=n;i++)
printf("%d ",a[i]);
getchar();getchar();
return 0;
}
这个是我们自己写快排的代码,其实在C和C++的库函数里面,有一个自带的快排函数qsort
这个函数的头文件:
#include <stdlib.h>
这个函数的书写格式,函数声明是这样:
void qsort(void *base, size_t nitems, size_t size, int (*compar)(const void *, const void*))
声明里面的参数的分别是:
base -- 指向要排序的数组的第一个元素的指针。
nitems -- 由 base 指向的数组中元素的个数。
size -- 数组中每个元素的大小,以字节为单位。
compar -- 用来比较两个元素的函数
这几个参数里面,唯独最后一个参数不好理解。最后一个参数,是要传给他一个比较函数,比较函数是什么?就是比较两个数大小的函数;从哪里找这个函数?自己写!!
是的,最后那个参数其实就是一个自己写的比较函数。
为了方便大家理解,我们举个例子来使用一下。
#include <stdio.h> /* printf */
#include <stdlib.h> /* qsort */
int values[] = { 40, 10, 100, 90, 20, 25 };// 自定义的一个序列
int compare (const void * a, const void * b)
{
return ( *(int*)a - *(int*)b );
}// 这个就是我们自己写的比较函数,用于比较a,b大小.如果a小于b,则返回值为负数(< 0),也即a会排在b的前面。同理,若a大于b,则a会排在b的后面。所以,这里的qsort()为从小到大即升序排序。如果需要从小到大,那么就返回b-a即可
int main ()
{
int n;
qsort (values, 6, sizeof(int), compare);
//调用qsort函数 values 所需要排序的序列的首地址;6 代表序列有6个元素;sizeof(int)因为是个int数组,所以每个元素的大小是sizeof(int);最后compare就是我们自己的比较函数
for (n=0; n<6; n++)
printf ("%d ",values[n]);
return 0;
}
这个就是qsort函数的实例,不是很理解的可以评论区留言,然后自己多上手试试,这个函数还是比较好用的,这么使用不比我们自己写一个快速排序或者冒泡排序来的快?!
如果在这个基础上,运动动态分配是可以实现一个排序程序的(就是任一序列进行排序),大家也可以上手试一试,不是很难。
好滴,今天的分享到此结束,对了,大伙儿圣诞节快乐哦!!