对于快速排序的最坏情况的时间复杂度为n^2,就是将升序数组进行降序排序.但是期望复杂度确实nlgn.
7.1 快速排序的描述
分解:数组A[p...r]被划分为两个(可能为空)子数组A[p...q-1]和A[q+1...r],使得A[p...q-1]中的每个元素都小于等于A[q],而A[q]也小于等于A[q+1...r]中的每个元素.其中,计算下标q也是划分过程的一部分.
解决:通过递归调用快速排序,对子数组A[p...q-1]和A[q+1...r]进行排序.
合并:因为子数组都是原址排序的,所以不需要合并操作:数组A[p...r]已经有序.
#include <stdio.h>
#include <stdlib.h>
void swap( int *px, int *py )
{
int temp = *px;
*px = *py;
*py = temp;
}
int partition( int arr[], int p, int r )
{
int x = arr[ r - 1 ];
int i = p;
int j = 0;
for ( j = p; j < r - 1; j++ ){
if ( arr[ j ] <= x ){
swap( &arr[ i ], &arr[ j ] );
i++;
}
}
swap( &arr[ i ], &arr[ r - 1 ] );
return i;
}
void quicksort( int arr[], int p, int r )
{
int q = 0;
if ( p < r ){
q = partition( arr, p, r );
quicksort( arr, p, q );
quicksort( arr, q + 1, r );
}
}
int main( void )
{
int arr[ 10 ];
int i = 0;
for ( i = 0; i < 10; i++ ){
arr[ i ] = 10 - i;
}
quicksort( arr, 0, 10 );
for ( i = 0; i < 10; i++ ){
printf("%d ", arr[ i ] );
}
printf("\n");
return 0;
}
![](http://static.oschina.net/uploads/space/2013/1010/200213_92Ax_1017135.png)
7.3 快速排毒的随机化版本
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void swap( int *px, int *py )
{
int temp = *px;
*px = *py;
*py = temp;
}
int partition( int arr[], int p, int r )
{
int x = arr[ r - 1 ];
int i = p;
int j = 0;
for ( j = p; j < r - 1; j++ ){
if ( arr[ j ] <= x ){
swap( &arr[ i ], &arr[ j ] );
i++;
}
}
swap( &arr[ i ], &arr[ r - 1 ] );
return i;
}
int randomized_partition( int arr[], int p, int r )
{
int i = rand() % ( r - p ) + p;
swap( &arr[ r - 1 ], &arr[ i ] );
return partition( arr, p, r );
}
void quicksort( int arr[], int p, int r )
{
int q = 0;
if ( p < r ){
q = randomized_partition( arr, p, r );
quicksort( arr, p, q );
quicksort( arr, q + 1, r );
}
}
int main( void )
{
int arr[ 10 ];
int i = 0;
srand( ( unsigned int ) time( NULL ) );
for ( i = 0; i < 10; i++ ){
arr[ i ] = 10 - i;
}
quicksort( arr, 0, 10 );
for ( i = 0; i < 10; i++ ){
printf("%d ", arr[ i ] );
}
printf("\n");
return 0;
}
程序输出:
习题7-1:
我被这道题弄崩溃了,我觉得书上的算法太坑爹了.........第一次发现,边界情况是如此的特殊,所以算法看起来比实际的复杂多了:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void swap( int *px, int *py )
{
int temp = *px;
*px = *py;
*py = temp;
}
int hoare_partition( int arr[], int p, int r )
{
int i = p;
int j = r;
int tempi;
int tempj;
int x = arr[ p ];
if ( r == p + 1 ){
if ( arr[ p ] > arr[ r ] ){
swap( &arr[ p ], &arr[ r ] );
}
return p;
}
while ( 1 ){
tempj = j;
while ( arr[ j ] >= x && j >= p ){
j--;
}
tempi = i;
while ( arr[ i ] <= x && i <= r ){
i++;
}
if ( i < j ){
swap( &arr[ i ], &arr[ j ] );
}
else{
if ( tempj == j ){ //最大值在最右边的特例
swap( &arr[ j ], &arr[ tempi ] );
j--;
}
else if ( j < p ){ //最小值在左边的特例
j = p;
}
break;
}
}
return j;
}
void quicksort( int arr[], int p, int r )
{
int q = 0;
if ( p < r ){
q = hoare_partition( arr, p, r );
quicksort( arr, p, q );
quicksort( arr, q + 1, r );
}
}
int main( void )
{
int arr[ 8 ] = { 2, 8, 7, 1, 3, 5, 6, 4 };
int i = 0;
quicksort( arr, 0, 7 );
for ( i = 0; i < 8; i++ ){
printf("%d ", arr[ i ] );
}
printf("\n");
return 0;
}
程序输出:
习题7-2:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void swap( int *px, int *py )
{
int temp = *px;
*px = *py;
*py = temp;
}
void partition( int arr[], int p, int r, int *q, int *t )
{
int x = arr[ r ];
int i = p - 1;
int j = 0;
int sameEle = 0;
for ( j = p; j <= r; j++ ){
if ( arr[ j ] < x ){
i++;
swap( &arr[ i ], &arr[ j ] );
}
else if ( arr[ j ] == x ){
i++;
swap( &arr[ i ], &arr[ j ] );
sameEle++;
}
}
swap( &arr[ i + 1 ], &arr[ r ] );
*q = i - sameEle;
*t = i;
for ( j = 0; j < i; j++ ){ //这里保证重复的元素放在最后
if ( arr[ j ] == x && arr[ j + 1 ] != x ){
swap( &arr[ j ], &arr[ j + 1 ] );
}
}
}
void quicksort( int arr[], int p, int r, int *q, int *t )
{
if ( p < r ){
int tempt;
int tempq;
partition( arr, p, r, q, t );
tempt = *t;
tempq = *q; //这里保证两次递归中指针的值不被改变
quicksort( arr, p, tempq, q, t );
quicksort( arr, tempt + 1, r, q, t );
}
}
int main( void )
{
int arr[ 8 ] = { 2, 8, 4, 1, 4, 5, 6, 4 };
int i = 0;
int q = 0;
int t = 0;
int *pq = &q;
int *pt = &t;
quicksort( arr, 0, 7, pq, pt );
for ( i = 0; i < 8; i++ ){
printf("%d ", arr[ i ] );
}
printf("\n");
return 0;
}
程序输出:
习题7-4:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void swap( int *px, int *py )
{
int temp = *px;
*px = *py;
*py = temp;
}
int partition( int arr[], int p, int r )
{
int x = arr[ r ];
int i = p - 1;
int j = 0;
for ( j = p; j < r; j++ ){
if ( arr[ j ] <= x ){
i++;
swap( &arr[ j ], &arr[ i ] );
}
}
swap( &arr[ i + 1 ], &arr[ r ] );
return i + 1;
}
void quicksort( int arr[], int p, int r )
{
while ( p < r ){
int q = partition( arr, p, r );
quicksort( arr, p, q - 1 );
p = q + 1;
}
}
int main( void )
{
int arr[ 8 ] = { 2, 8, 7, 1, 3, 5, 6, 4 };
int i = 0;
quicksort( arr, 0, 7);
for ( i = 0; i < 8; i++ ){
printf("%d ", arr[ i ] );
}
printf("\n");
return 0;
}
程序输出: