快速排序是一种被广泛应用的排序算法,其平均时间复杂度为O(NlogN),最坏情况下的时间复杂度为O(N^2);

1、基本思路:

快速排序是一种基于分治思想的排序算法,对一个数组A[left, …, right] 进行排序的的分治过程的三个步骤为:

1)分解:将数组A[left, … , right] 划分为两个子数组(可能为空)A[left, … , p] 及 A[p+1, … , right], 使得A[left, …, p] 中的每一个值都小于等于A[p], A[p+1, … , right]中的每一个数都大于等于A[p], 此处的p作为划分数组A的一个枢纽元;

2)解决:通过递归调用快速排序,对于数组A[left, …, p] 及 A[p+1, … , right]进行排序;

3)合并:因为两个子数组是就地排序,所以将它们合并是并不需要进行其他操作,整个数组已经完成排序;

以上步骤可以由下列过程表示:

void QuickSort(int A[], int left, int right)
{
    //当left < right时, 对其排序
    if(left < right) 
    {
        povit = PARTITION(A, left, right);    //得到枢纽元povit
        QuickSort(A, left, p)j;               //对povit两侧是子数组进行排序
        QuickSort(A, p + 1, right);
    }


}

2、程序实现:

在快速排序算法中,枢纽元的选取不是惟一的,可以有多种选取方法,通常情况下有一下几种选取方法:

1)选取数组(子数组)中的第一个数(或最后一个数)作为枢纽元;

2)选取数组(子数组)的中值作为枢纽元;

3)随机选取枢纽元;

1)选取数组(子数组)中的第一个数作为枢纽元:

算法实现如下:

//C代码:
//1)选取数组(子数组)中的第一个元素作为枢纽元

void QuickSort(int A[], int left, int right)
{
    int i  = 0;
    int j = 0;
    int povit = 0;    
    
    //当left < right时,排序
    if(left < right)
    {
        i = left;
        j = right;
        povit = A[i];    //选取第一个值作为枢纽元    

        //根据枢纽元对数组分解
        while( i < j  && A[j] >= povit )
        {
            j--;
        }        
        if( i < j )
        {
            A[i] = A[j];
            i++;
        }

        while( i < j && A[i] <= povit )
        {
            i++;
        }
        if( i < j )
        {
            A[j] = A[i];
            j--;
        }

        A[i] = povit     //得到A[left, ..., i] 和A[i+1, ..., right]

        QuickSort(A, left, i);    //对左侧子数组排序
        QuickSort(A, i + 1, right);    //对右侧子数组排序

    }

}
 选取数组(子数组)中的最后一个值作为枢纽元的情况与选取数组中的第一个枢纽元的情况类似;
2)选取数组(子数组)的中值作为枢纽元:
//C 代码
//2)选取中值作为枢纽元
//取A[left]、A[(left+right)/2]和A[right]三者的中值作为枢纽元

void swap(int *a, int* b)
{
    int temp = 0;
    
    temp = *a;
    *a = *b;
    *b = temp;

}

void QuickSort(int A[], int left, int right)
{
    int i = 0;
    int j = 0;
    int povit = 0;
    int center = 0;

    if(left < right)
    {
        //取A[left]、A[(left+right)/2]和A[right]三者的中值作为枢纽元

         int center = ( left + right )/2;
        if(A[left] > A[center] )
            swap( &A[left], &A[center] );
        if( A[center] > A[right] )
            swap( &A[center], &A[right] );
        if( A[left] > A[center] )
            swap( &A[left], &A[right] );
        
        i = left - 1;
        j = right;
        povit = A[center];    //中值作为枢纽元

        while( i <j)
        {
            while( i < j && A[++i] <= povit );
            while( i < j && A[--j] >= povit );

            if( i < j)
                swap(&A[i], &A[j] );
        }
        
        //通过 i- 1, 将A分解为两个子数组,并对其排序
        QuickSort( A, left, i - 1);
        QuickSort( A, i, right);    

    }

}

 

3)随机选取枢纽元;

随机选取枢纽元与选择中值作为枢纽元的情况基本相同,可以将选择中值的情况看做是选择随机枢纽元的一种特殊情况;

posted on 2014-05-25 20:18  鹏翔天际  阅读(212)  评论(0编辑  收藏  举报