快速排序

它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
1) 程序开始执行,此时low=1,high=L.length=9。第4行,我们将L.r[low]=L.r[1]=50赋值给枢轴变量pivotkey,如图9-9-1所示。
这里写图片描述
2) 第5~13行为while循环,目前low=1< high=9,执行内部语句。
3) 第7行,L.r[high]= L.r[9]=20≯pivotkey=50,因此不执行第8行。
4) 第9行,交换L.r[low]与L.r[high]的值,使得L.r[1]=20,L.r[9]=50。为什么要交换,就是因为第7行的比较知道,L.r[high]是一个比pivotkey=50(即L.r[low])还要小的值,因此它应该交换到50的左侧,如图9-9-2所示。
这里写图片描述
5) 第10行,当L.r[low]= L.r[1]=20,pivotkey=50,L.r[low]< pivotkey,因此第11行,low++,此时low=2。继续循环,L.r[2]=10<50,low++,此时low=3。L.r[3]=90>50,退出循环。
6) 第12行,交换L.r[low]=L.r[3]与L.r[high]=L.r[9]的值,使得L.r[3]=50,L.r[9]=90。此时相当于将一个比50大的值90交换到了50的右边。注意此时low已经指向了3,如图9-9-3所示。
这里写图片描述
7) 继续第5行,因为low=3< high=9,执行循环体。
8) 第7行,当L.r[high]= L.r[9]=90,pivotkey=50,L.r[high]>pivotkey,因此第8行,high–,此时high=8。继续循环,L.r[8]=60>50,high–,此时high=7。L.r[7]=80>50,high–,此时high=6。L.r[6]=40<50,退出循环。
9) 第9行,交换L.r[low]=L.r[3]=50与L.r[high]=L.r[6]=40的值,使得L.r[3]=40,L.r[6]=50,如图9-9-4所示。
这里写图片描述
10) 第10行,当L.r[low]= L.r[3]=40,pivotkey=50,L.r[low]< pivotkey,因此第11行,low++,此时low=4。继续循环L.r[4]=30<50,low++,此时low=5。L.r[5]=70>50,退出循环。
11) 第12行,交换L.r[low]=L.r[5]=70与L.r[high]=L.r[6]=50的值,使得L.r[5]=50,L.r[6]=70,如图9-9-5所示。
这里写图片描述
12) 再次循环。因low=5< high=6,执行循环体后,low=high=5,退出循环,如图9-9-6所示。
这里写图片描述
13) 最后第14行,返回low的值5。函数执行完成。接下来就是递归调用“QSort(L,1,5-1);”和“QSort(L,5+1,9);”语句,对{20,10,40,30}和{70,80,60,90}分别进行同样的Partition操作,直到顺序全部正确为止。我们就不再演示了。
通过这段代码的模拟,大家应该能够明白,Partition函数,其实就是将选取的pivotkey不断交换,将比它小的换到它的左边,比它大的换到它的右边,它也在交换中不断的更改自己的位置,直到完全满足这个要求为止。

具体实现(c):
/* 对顺序表L中的子序列L->r[low..high]作快速排序 */
void QSort(SqList *L,int low,int high)
{
int pivot;
if(low< high)
{
pivot=Partition(L,low,high); /* 将L->r[low..high]一分为二,算出枢轴值pivot */
QSort(L,low,pivot-1); /* 对低子表递归排序 */
QSort(L,pivot+1,high); /* 对高子表递归排序 */
}
}

/* 交换顺序表L中子表的记录,使枢轴记录到位,并返回其所在位置 */
/* 此时在它之前(后)的记录均不大(小)于它。 */
int Partition(SqList *L,int low,int high)
{
int pivotkey;
pivotkey=L->r[low]; /* 用子表的第一个记录作枢轴记录 */
while(low< high) /* 从表的两端交替地向中间扫描 */
{
while(low< high&&L->r[high]>= pivotkey)
high–;
swap(L,low,high); /* 将比枢轴记录小的记录交换到低端 */
while(low< high&&L->r[low]<= pivotkey)
low++;
swap(L,low,high); /* 将比枢轴记录大的记录交换到高端 */
}
return low; /* 返回枢轴所在位置 */
}

范例代码:

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--;
                swap(i, j);  //交换两个数在数组中的位置
               //再找右边的
               while(a[i]<= temp && i<j)
                        i++;
                swap(i, j);  //交换两个数在数组中的位置


}


quicksort(left,i-1);//继续处理左边的,这里是一个递归的过程
quicksort(i+1,right);//继续处理右边的 ,这里是一个递归的过程

}
void swap(int i, int j)
{
int t;
if(i< j)
{
t=a[i];
a[i]=a[j];
a[j]=t;
}
}
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;

}

最优的情况下,快速排序算法的时间复杂度为O(nlogn)。
就空间复杂度来说,主要是递归造成的栈空间的使用,最好情况,递归树的深度为log2n,其空间复杂度也就为O(logn),最坏情况,需要进行n-1递归调用,其空间复杂度为O(n),平均情况,空间复杂度也为O(logn)。
快速排序的优化:
三数取中法(即三个关键字先进性排序,,将中间数作为枢纽,一般取左端、右端和中间三个数,也可随机取。)选取枢轴 pivotkey;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值