快速排序算法

第一:快速排序+递归调用

1)选取标点,一般取第一个数,空出一个坑A。

2)从右边标志向左扫描,找到第一个比自己小的数,然后将数填充到位置A中,留出一个坑B,然后将左边标志指向左边坑后面的第一个数;

3)从左边标志向右扫描,找到第一个比自己大的数,然后将数填到位置B中,留出一个坑A,然后将右边标志指向右边坑前面的第一个数上。

4)重复2) 3)知道左边标志遇到右边标志

5)将标点数填到左边标志的坑中,返回左边标志的位置。

  

View Code  
对于快排提高效率的地方主要地方时如何选取标点数据。目前常用的有随机快排(不是选取第一个数,而是随机选取一个数)、平衡快排(从第一个、中间一个、最后一个分部取出三个树,然后选取他们当中接近中值的那个数)。

为了分析快速排序的时间复杂度,请先看下面的主定理:

 

主定理: T [n] = aT[n/b] f (n)

其中 >= and b > 1 是常量 并且 f (n) 是一个渐近正函数, 为了使用这个主定理,您需要考虑下列三种情况:

想必大家都知道快速排序的过程,如果对这个过程有什么不了解,请参考下文:

http://www.cnblogs.com/pugang/archive/2012/06/27/2565093.html

快速排序的每一次划分把一个 问题分解成两个子问题,其中的关系可以用下式表示:

T[n] = 2T[n/2] + O(n) 其中O(n)PARTITION()的时间复杂度,对比主定理,

 T [n] = aT[n/b] f (n)

我们的快速排序中:a = 2, b = 2, f(n) = O(n)

那么为什么还有最坏情况呢?

考虑如下极端情况,

T[n] = T[n-1] + T[1] + O(n),

问题来了,这一次的划分白玩了,划分之后一边是一个,一边是n-1个,这种极端情况的时间复杂度就是O(n2).

#include <stdio.h>
#include <stdlib.h>

typedef int DataType;
int quick_snort(DataType data[],int lf,int rt)
{
         DataType flag;
         int ilf,jrt;
         ilf = lf;
         jrt = rt;
         flag = data[ilf];
         while(ilf < jrt){
               while(ilf< jrt && data[jrt] >flag)
                    jrt--;
                if(ilf < jrt){
                        data[ilf]  =  data[jrt];
                        ilf++;
                }
                while(ilf < jrt && data[ilf] <= flag)
                        ilf++;
                if(ilf < jrt){
                        data[jrt] = data[ilf];
                        jrt--;
                }
         }
         data[ilf] = flag;
         return ilf;
}
void quick(DataType data,int lf,int rt)
{
    if(lf < rt){
          int ilf  = quick_snort(data,lf,rt);
          quick(data,lf,ilf-1);
          quick(data,ilf+1,rt);
    }
}

int main()
{
    int i=0;
    int data[10]={9,8,7,6,5,4,3,2,1,0};
    quick(data,0,9);
    for(i=0;i<10;i++)
            printf("%d ",data[i]);
    printf("\nHello world!\n");
    return 0;
}
原文地址:https://www.cnblogs.com/gogly/p/2737264.html