摘要:本文描述了快速排序的算法原理,给出了算法的逐步排序过程以及算法的实现。最后对算法的性能进行了分析。
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) |
交换 | 冒泡排序 | 快排 |
插入 | 插入排序 | 希尔 |
选择 | 选择排序 | 堆排序 |