快速排序算法原理与实现

摘要:本文描述了快速排序的算法原理,给出了算法的逐步排序过程以及算法的实现。最后对算法的性能进行了分析。

1. 问题描述

输入:n个数的序列<a1,a2,a3,...,an>。
输出:原序列的一个重排<a1*,a2*,a3*,...,an*>;,使得a1*<=a2*<=a3*<=...<=an*。

2.问题分析

快速排序:最基本的思想就是通过一趟排序,将待排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录进行排序,以达到整个序列有序。

排序过程:(对 data[s, t] 排序)

(1)初始时令i=s,j=t
(2)首先从j所指位置向前搜索第一个关键字小于x的记录,并和rp交换
(3)再从i所指位置起向后搜索,找到第一个关键字大于x的记录,和rp交换
(4)重复上述两步,直至i==j为止
(5)再分别对两个子序列进行快速排序,直到每个子序列只含有一个记录为止

快速排序算法原理与实现_第1张图片


3. 算法实现

template <typename T>
void Partition( CVector<T> &vec, int start, int end )
{
    int left = start;
    int right = end;
    T key = vec[left];
   
    while( left < right )
    {
        while( key <=vec[right] && left < right )
            right--;
        vec[left] = vec[right];

        while( key >=vec[left] && left <right )
            left++;
        vec[right] = vec[left];
    }

    vec[left] = key;

    if( start < left-1 )
        Partition( vec, start, left-1 );
    if( left+1 < end )
        Partition( vec, left+1, end );
}

template <typename T>
void QuickSort( CVector<T> &vec )
{
    Partition( vec, 0, vec.GetSize()-1 );
}

测试:

#define  DATA_MAGNITUDE 100

double random(double start, double end)
{
    return start+(end-start)*rand()/(RAND_MAX + 1.0);
}

int main(int argc, char **argv)
{
    CVector<int> vec1(10,2);
    CVector<int> vec2(DATA_MAGNITUDE);
    CVector<char> vec_txt(1000,'a');

    //====================================================================
    srand( unsigned(time(0)));
    for ( int i=0; i<DATA_MAGNITUDE; i++ )
    {
        //vec2.PushBack( (int)rand()%DATA_MAGNITUDE );
        vec2.PushBack( (int)random(0, DATA_MAGNITUDE) );
    }
    unsigned int size = 20<DATA_MAGNITUDE? 20:DATA_MAGNITUDE;
    for ( size_t i =0; i < size; i++ )
    {
        cout<<vec2[i]<<" ";
    }
    cout<<endl;

    //InsertSort<int>( vec2, 0, vec2.GetSize()-1 );
    //BubbleSort<int>( vec2 );
    //SelectSort<int>( vec2 );
    //ShellSort<int>( vec2 );
    QuickSort<int>( vec2 );
    for ( size_t i =0; i < size; i++ )
    {
        cout<<vec2[i]<<" ";
    }
    cout<<endl;
    return 0;
}

4. 算法分析

快速排序应该说是所有算法里面最快的(特殊情况除外)。快排适用于数据的分布基本随机的情况(如果是基本有序的数据,将大大影响Patition的效果,从而降低快排的性能)。

影响快排性能的主要因素是初始值key(用于Patition的值)的选取, 理想状态是每一次选取的key都可以把数据分为均等的2部分。 

比如说{ 49, 38, 65, 97, 13, 27 }:

if  key = 97 ,那么Patition = { 49, 38, 65, 13, 27   } 97 {  } 。 这么分割的效果是非常差的,所以说QuickSort不适用于基本有序的数据。

if  key = 38,then Patition = { 13, 27 } 38 { 49, 65, 97 }

所以有些QuickSort程序会在对数据进行预处理,把数据打乱。


快速排序的时间复杂度为n*log(n)。

关于nlog(n)的推导会在另一篇文章中解释。

快速排序的时间复杂度nlogn是如何推导的??

===============================================================================

分类
基础排序O(n^2)
高级排序O(nlogn)
交换 冒泡排序 快排
插入 插入排序 希尔
选择 选择排序 堆排序

你可能感兴趣的:(数据结构,算法,快速排序)