请扫码加公众号,周三六定时更新
闲话不多说了,给出一个C语言实现的快速排序,快速排序部分主要源于C语言之父的黑皮书,因为原书是对字符串进行排序的,我稍微改了一下弄成整型的。
#include<stdio.h>
#include<stdlib.h>
voidswap(int A[],int i,int j);
voidqsort1(int A[],int i,int j);
intmyrand(int left,int right);
intmain(void)
{
int A[10],i;
for(i=0;i<10;i++)
A[i]=myrand(0,99);
qsort1(A,0,9);
for(i=0;i<10;i++)
printf("%5d",A[i]);
}
intmyrand(int left,int right)
{
return(int)((rand()*1.0/RAND_MAX)*(right-left)+left);
}
voidqsort1(int A[],int left,int right)
{
int i,last,mid;
mid=(left+right)/2;
if(left>=right)
return ;
swap(A,left,mid);
last=left;
for(i=left+1;i<=right;i++)
if(A[i]<A[left])
swap(A,++last,i);
swap(A,left,last);
qsort1(A,left,last-1);
qsort1(A,last+1,right);
}
voidswap(int A[],int i,int j)
{
int temp;
temp=A[i];
A[i]=A[j];
A[j]=temp;
}
main函数的工作分为三部分,第一个for循环迭代为数组赋予随机值,然后qsort1()用来进行随机排序,最后一个for循环则用来输出数组。
跟随在main函数后面的三个函数:myrand, qsort1, swap。 第一个用来制造给定区间的随机整数, 第二个即是随机排序(有个1是因为我之前编译了一个快速排序做自己的库,不用在意那个1), 第三个函数用来交换数组中的两个元素。
制造随机整数的我就不赘述了,要是看不懂后台私戳吧(这个函数很简单,相信聪慧的你们一定能看懂)、
swap(intA[],int i,int j) 这个函数通过一个temp来交换A数组的第i个元素和第j个元素。
好了,开始介绍快速排序啦,瞪大眼睛
inti,last,mid; 三个整型变量,i用在后面的遍历,mid则表示数组中间值,last用来说明最后枢纽元的位置(枢纽元是什么请参考上上次推文)。
mid=(left+right)/2; left是数组第一个元素的下标,right是最后一个的,所以这个mid就能表示中间值的了。
A【3】=80也就是mid表示的值啦。
swap(A,left,mid);
这一条语句是把第一个元素和中间位置元素对换,目的是把中间元素做枢纽元。
为什么中间元素做枢纽元?
因为在大多数情况下,我们会假定中间元素往往会接近序列的中值,用这个模拟的中值做枢纽元能将大约序列一半的元素分在枢纽元左边,一半分在右边。
这条语句结束后
为什么想接近一半分在左边,一半分在右边?
因为这样会使得快速排序接近最快情况,快速排序最理想的情况就是一半元素小于枢纽元,一半元素大于枢纽元。
for(i=left+1;i<=right;i++)
if(A[i]<A[left])
swap(A,++last,i);
在这个循环中,i从A【1】=5开始遍历元素,把小于枢纽元A【0】=80的放在last左边,
在对i=1以后
对i=2执行后,
直到最后i=6,last=6。last=7的原因是除了55-34的所有元素都小于80,所以last右边没有比80的值。
swap(A,left,last);
第一句swap将枢纽元放到last位置上。
接下来,原来七个元素的数组被分成了两部分,一部分小于80,另一部分大于80(因为没有,所以假想后面还有元素把)
小于的部分其实就是从left到last-1,称这部分为A
而大于的部分则从last+1到right
接下来,我们分别递归A和B
qsort1(A,left,last-1);
qsort1(A,last+1,right);
第一句递归A部分,第二句话则递归B部分。
第一句和前面的过程基本类似。
第二句中因为last+1=7>right=6,所以这一层的递归直接结束了,没有进行任何操作。