算法原理
定义quick_sort
函数,对A[left..right]
进行排序
首先检查数组大小,若数组大小为1或为空,则直接返回
然后调用partition
函数,返回pivot
为数组中的某个位置,位于pivot
之前的元素A[left..pivot-1]
均小于A[pivot]
,位于pivot
之后的元素A[pivot+1..right]
均大于A[pivot]
最后递归调用quick_sort
函数,对pivot
分开的两部分A[left..pivot-1]
和A[pivot+1..right]
进行排序
void quick_sort( vector<int>& A, int left, int right )
{
if( left >= right )
return;
int pivot = partition( A, left, right );
quick_sort( A, left, pivot - 1 );
quick_sort( A, pivot + 1, right );
}
定义partition
函数
int partition( vector<int>& A, int left, int right )
{
while( left < right )
{
while( left < right && A[left] <= A[right] )
right--;
swap( A[left], A[right] ); // 违反了A[left] <= A[right],把它们交换
while( left < right && A[left] <= A[right] )
left++;
swap( A[left], A[right] );
}
return left; // 最终left和right相等
}
(1)固定left
,移动right
,找到第一处A[left] > A[right]
的位置(违反升序),交换它们
(2)固定right
,移动left
,找到第一处A[left] > A[right]
的位置(违反升序),交换它们
上述(1)(2)两步交替进行,直到left
和right
相等,即为pivot
的位置
注:第6行right--
第11行left++
可以交换
完整代码如下
#include <stdio.h>
#include <time.h>
#include <vector>
#include <algorithm>
#define MAXN 50
using namespace std;
void display( vector<int>& s )
{
for( int i = 0; i < s.size(); i++ )
printf( "%d ", s[i] );
printf( "\n" );
}
bool check( vector<int>& s1, vector<int>& s2 )
{
for( int i = 0; i < s1.size(); i++ )
if( s1[i] != s2[i] )
return false;
return true;
}
int partition( vector<int>& A, int left, int right )
{
while( left < right )
{
while( left < right && A[left] <= A[right] )
right--;
swap( A[left], A[right] ); // 违反了A[left] <= A[right],把它们交换
while( left < right && A[left] <= A[right] )
left++;
swap( A[left], A[right] );
}
return left; // 最终left和right相等
}
void quick_sort( vector<int>& A, int left, int right )
{
if( left >= right )
return;
int pivot = partition( A, left, right );
quick_sort( A, left, pivot - 1 );
quick_sort( A, pivot + 1, right );
}
int main()
{
srand( (unsigned)time(NULL) );
int nums[MAXN];
for( int i = 0; i < MAXN; i++ )
nums[i] = rand() % 100;
vector<int> s1( nums, nums + MAXN );
vector<int> s2( nums, nums + MAXN );
quick_sort( s1, 0, s1.size() - 1 );
sort( s2.begin(), s2.end() );
printf( "s1: " );
display(s1);
printf( "s2: " );
display(s2);
printf( "Result: %s\n", check( s1, s2 ) ? "Accepted" : "Wrong Answer" );
return 0;
}
应用:数组中的第k小(大)
LeetCode 215. Kth Largest Element in an Array
因为是从大到小数第k个,所以利用partition函数(降序版)解决
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
return helper( nums, k, 0, nums.size() - 1 );
}
int helper( vector<int>& nums, int k, int left, int right )
{
int pivot = partition( nums, left, right );
int len1 = pivot - left + 1;
if( k == len1 )
return nums[pivot];
else if( k < len1 )
return helper( nums, k, left, pivot - 1 );
else
return helper( nums, k - len1, pivot + 1, right );
}
int partition( vector<int>& nums, int left, int right )
{
while( left < right )
{
while( left < right && nums[left] >= nums[right] ) // 降序版
right--;
swap( nums[left], nums[right] );
while( left < right && nums[left] >= nums[right] ) // 降序版
left++;
swap( nums[left], nums[right] );
}
return left;
}
};