快速排序算法原理与实现

本文详细介绍了快速排序算法的原理,包括其基本思想、排序过程及算法实现。重点分析了快速排序的时间复杂度为nlogn,并指出该算法在数据基本随机时表现最佳,但对基本有序的数据效率较低。此外,文章还提到了影响快排性能的关键因素——key的选择,以及预处理数据的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

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)再分别对两个子序列进行快速排序,直到每个子序列只含有一个记录为止



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)
交换冒泡排序快排
插入插入排序希尔
选择选择排序堆排序

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值