排序:快速排序

时间复杂度 最理想 O(nlogn) 最差时间O(n^2)

像合并排序一样,快速排序也是基于分治模式的。下面是对一个典型子数组A[p..r]排序的分治过程的三个步骤:

分解:

数组A[p..r]]被划分成两个(可能空)子数组A[p..q-1]和A[q+1..r],使得A[p..q-1]中的每个元素都小于等于A(q),而且,小于等于A[q+1..r]中的元素。下标q也在这个划分过程中进行计算。

解决:

通过递归调用快速排序,对子数组A[p..q-1]和A[q+1..r]排序。

合并:

因为两个子数组是就地排序的,将它们的合并不需要操作:整个数组A[p..r]已排序


快速排序:

QUICKSORT(A,p,r)
if p<r
   then q=PARTITION(A,p,r)
        QUICKSORT(A,p,q-1)
        QUICKSORT(A,q+1,r)

数组划分:

PARTITION(A,p,r)
x=A[r]
i=p-1
for j=p to r-1
    do if A[j]<=x
          then i=i+1
               exchange A[i]<->A[j]
exchange A[i+1]<->A[r]
return i+1


具体可以看下图



可参照c代码:

#include <stdio.h> 

int partion(int a[],int p,int r){
    int x=a[r], i=p-1,tem;
    for (int j=p;j<r;j++){ 
        if (a[j]<=x){
            tem=a[i+1];
            a[i+1]=a[j];
            a[j]=tem;
            i++;
        }
    }
    tem=a[r];
    a[r]=a[i+1];
    a[i+1]=tem;
    return i+1;
}
 
void QuickSort(int a[],int p,int r){
    if (p<r){
        int q=partion(a,p,r);
        QuickSort(a,p,q-1);
        QuickSort(a,q+1,r);
    }
}
 
void main(){
    int array[]={0,-2,11,-4,13,-5,14,-43};
    QuickSort(array,0,7);
    for(int i=0;i<=7;i++)
        printf("%d ",array[i]);
    printf("\n");
 } 

选取枢纽元问题

1、糟糕的方法 

     通常的做法是选择数组中第一个元素作为枢纽元,如果输入是随机的,那么这是可以接受的。但是,如果输入序列是预排序的或者是反序的,那么依据这样的枢纽元进行划

分则会出现相当糟糕的情况,因为可能所有的元素不是被划入S1,就是都被划入S2中。 

2、较好的方法 

    一个比较好的做法是随机选取枢纽元,一般来说,这种策略是比较妥当的。 

3、三数取取中值方法 

    例如,输入序列为  8, 1, 4, 9, 6, 3, 5, 2, 7, 0 ,它的左边元素为8,右边元素为0,中间位置|_left+right)/2_|上的元素为6,于是枢纽元为6.显然,使用三数中值分割法消除了预

排序输入的坏情形,并且减少了快速排序大约5%(此为前人实验所得数据,无法具体证明)的运行时间。


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值