快速排序的思想
快速排序的思想:通过一趟可以将一组元素划分两个部分,一个部分大于基准数,另外一个部分小于基准数。然后再对这两个部分进行排序,典型的分治思想。
一、单路快速排序
int partition ( int * arr, int l, int r)
{
int i = 0 , j = 0 ;
int t = rand ( ) % ( r - l + 1 ) + l;
int tmp = 0 ;
tmp = arr[ t] ;
arr[ t] = arr[ l] ;
arr[ l] = tmp;
int v = arr[ l] ;
j = l;
for ( i = l + 1 ; i <= r; i ++ )
{
if ( v > arr[ i] )
{
j ++ ;
tmp = arr[ i] ;
arr[ i] = arr[ j] ;
arr[ j] = tmp;
}
}
tmp = arr[ l] ;
arr[ l] = arr[ j] ;
arr[ j] = tmp;
return j;
}
void _singleWay_quickSort ( int * arr, int l, int r)
{
if ( l >= r)
return ;
int p = partition ( arr, l, r) ;
_singleWay_quickSort ( arr, l, p - 1 ) ;
_singleWay_quickSort ( arr, p + 1 , r) ;
}
void singleWay_quickSort ( int * arr, const int n)
{
srand ( unsigned ( time ( NULL ) ) ) ;
_singleWay_quickSort ( arr, 0 , n - 1 ) ;
}
二、双路快速排序
int partition_2 ( int * arr, int l, int r)
{
int i = l + 1 , j = r;
int t = rand ( ) % ( r - l + 1 ) + l;
int tmp = 0 ;
tmp = arr[ t] ;
arr[ t] = arr[ l] ;
arr[ l] = tmp;
int v = arr[ l] ;
while ( 1 )
{
while ( arr[ i] < v && i <= r)
i ++ ;
while ( arr[ j] > v && j >= l + 1 )
j -- ;
if ( i > j) break ;
tmp = arr[ i] ;
arr[ i] = arr[ j] ;
arr[ j] = tmp;
i ++ ;
j -- ;
}
tmp = arr[ l] ;
arr[ l] = arr[ j] ;
arr[ j] = tmp;
return j;
}
void _twoWay_quickSort ( int * arr, int l, int r)
{
if ( l >= r)
return ;
int p = partition_2 ( arr, l, r) ;
_singleWay_quickSort ( arr, l, p - 1 ) ;
_singleWay_quickSort ( arr, p + 1 , r) ;
}
void twoWay_quickSort ( int * arr, const int n)
{
srand ( unsigned ( time ( NULL ) ) ) ;
_twoWay_quickSort ( arr, 0 , n - 1 ) ;
}
三、三路快速排序
void _threeWay_quickSort ( int * arr, int l, int r)
{
if ( l >= r)
return ;
int t = rand ( ) % ( r - l + 1 ) + l;
int tmp = 0 ;
tmp = arr[ t] ;
arr[ t] = arr[ l] ;
arr[ l] = tmp;
int v = arr[ l] ;
int lt = l;
int i = l + 1 ;
int gt = r + 1 ;
while ( i < gt)
{
if ( arr[ i] < v)
{
tmp = arr[ i] ;
arr[ i] = arr[ ++ lt] ;
arr[ lt] = tmp;
i ++ ;
}
else if ( arr[ i] > v)
{
tmp = arr[ i] ;
arr[ i] = arr[ -- gt] ;
arr[ gt] = tmp;
}
else
{
i ++ ;
}
}
tmp = arr[ lt] ;
arr[ lt] = arr[ l] ;
arr[ l] = tmp;
_threeWay_quickSort ( arr, l, lt- 1 ) ;
_threeWay_quickSort ( arr, gt, r) ;
}
void threeWay_quickSort ( int * arr, const int n)
{
srand ( unsigned ( time ( NULL ) ) ) ;
_threeWay_quickSort ( arr, 0 , n - 1 ) ;
}
四、复杂度分析
递归的深度是:logn
时间复杂度:O(nlogn)
空间复杂度:O(nlogn)
五、三种快速排序算法的比较
1、在比较元素较少的情况下,可以使用插入排序、冒泡排序等算法
2、包含大量重复元素的数组,三路排序有巨大的优势
3、一般的数组和近乎有序的数组,三路排序不占优势,可以使用双路排序