十大排序算法——快速排序
在对于刚接触编程这个领域的同学,对排序还没有一定的了解的时候,就光是听到快速排序这个名称就会觉得很有吸引力,这个名字取得粗鲁且自信,让人不得不想去了解一下他自信的来源
快速排序其实是对冒泡排序的一种改进,名字里面的快速两个字得确也有自信的实力,它相对于其他几种排序来说效率较高,速度更快,但对于初学者而言,快速排序还是很难理解的,因为快速排序的一些特殊性,现在很多公司也会去选择它作为面试的考题,如果仅仅是依靠背代码,默写的方式的话估计很难去把快速排序写好,所以我们这个时候就得知道思路的一个重要性,只有把它的思想理解到位,我们才能更快的把快速排序学会。
首先,我们先来看一下快速排序的一个概念
快速排序是指通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行之前的操作,以此达到整个数据变成有序序列。
我们根据它的概念来详细看一下快速排序的思路
第一步如图1-1所示,先得去找一个基准数,一般来说数组第一个为基准数,现在可以理解为数组第一个数赋值给了key,成为基准数,数组的第一个位置产生了空缺(有位置没人坐)
int key = a[i];
再去找到一个最左边的下标,一个最右边的下标(其实就是长度减一)
int left = 0, int right = 6;
图1-1
(若出稿请在素材中更换此图,删除本句话)
因为左右两个下标是不会变动的,所以后期为了我们数组左右两边的数能够和基准数更好的进行比对,我们再去定义两个下标i,j分别等于left,right(如图1-2所示)
int i = left,j = right;
i 和 j就会一个从左边进行比较,一个从右边进行比较,记录每次比较之后的下标
图1-2
接下来从右边第一个数开始和基准数对比,该数如果大于基准数的话(a[j] > key),它的位置则不变,继续下一个数的对比(j--),如果小于基准数的话(a[j] < key),就结束右边的对比,该数就放到空缺的位置上面去(a[i] = a[j]),新的空缺位产生 (如图1-3所示)
while( (a[j] > key))
{
j--;
}
a[i] = a[j];
图1-3
(若出稿请在素材中更换此图,删除本句话)
接下来再从左边的数开始和基准数对比,如果该数比基准数小(a[i] < key),则位置保持不变,继续下一个数的对比(i++),如果比基准数大(a[i] > key)则结束左边的对比,该数移到空缺位(a[j] = a[i]),新的空缺位产生(如图1-4所示)
while( (a[i] < key))
{
i++;
}
a[j] = a[i];
图1-4
(若出稿请在素材中更换此图,删除本句话)
继续从右边上一次的位置进行之前相同的操作(如图1-5所示)
图1-5
(若出稿请在素材中更换此图,删除本句话)
现在就回到了左边,我们可以清晰的看到i 和 j已经相遇了那这个时候第一次对比结束,将基准数放回最后的空缺位置,a[i] = key;
第一次快排结束(如图1-6所示)
这时候聪明的同学就会发现一个隐藏条件,也是循环的退出条件 i < j
图1-6
(若出稿请在素材中更换此图,删除本句话)
第一次快排结束之后整个排序并没有结束,接下来我们通过递归继续剩下来的对比,由之前这个基准数为界,划分为左右两部分,两部分同时进行第一次快排相同的步骤,直到全部比较完变成一个有序的数组
sort(a,left,i-1);
sort(a,i+1,right);
以上呢,是数组实现快速排序的基本步骤,一些重点的代码部分也写了出来,为的就是让同学们学会将思想转化为代码
那接下来我们来一起看看快速排序的完整代码
#include <stdio.h>
void sort(int a[],int left,int right)
{
int i = left,j = right;
int key = a[i];
if(left >= right) //左边始终要小于我们的右边,如果等于结束整个程序
return;
while(i < j) // 每次快排退出条件
{
while((i < j) && (a[j] > key))
{
j--;
}
a[i] = a[j];
while((i < j) && (a[i] < key)) // 这里的i < j防止上面的j减过头导致程序出现错误
{
i++;
}
a[j] = a[i];
}
a[i] = key;
sort(a,left,i-1); //递归将数组分成两部分同时进行快排
sort(a,i+1,right); // i 就是第一次快排相遇的下标位置
}
int main()
{
int i;
int a[]={2,1,5,4,6,3};
int len = sizeof(a)/sizeof(a[0]);
sort(a,0,len-1); //传参,left = 0,right = 长度 - 1
for(i = 0; i < len; i++)
{
printf("%d",a[i]);
}
printf("\n");
return 0;
}