partition算法
partition算法就是把数组分割成几部分,对于快速排序中的分割算法就是把数组分割成大于某个数的一部分和小于一个数的一部分
partition方法从目的上看是达到以下三点:
- 选中数组中某一个元素,即为suanz(可以是任意点,可以选起始点,终止点,或者中间任意一个点);
- 扫描整个数组,凡是小于suanz的全部放到数组左端,大于suanz的放到数组的右端;
- 最后将suanz放到数组中间的位置,suanz左边全部都是小于它的数字,右边反之,最后返回suanz的位置信息;
采用基础的扫描数组的方法可以实现,比如:
int suanz = nums[begin];//也可以是在begin和end之间的随机数
//凡是小于suanz的全部放到数组左端
int pos = begin;
for (int i = begin + 1; i < end; ++i)
{
//对于nums[i]大于suanz的元素不用管,因为其在suanz的右侧
if (nums[i] < suanz)
{
//处于begin和pos之间的数是确定比suanz小的元素
pos++;
if (i != pos) //避免自身交换
swap(nums[pos], nums[i]);
}
}
//将suanz放到分界处,注意这里的nums[pos]是应该放到suanz左侧的
swap(nums[pos], suanz);
//对于partition函数来说,输出应为pos
为了提高效率,我们可以从数组的两端同时向另一侧进行扫描,把左侧找到的大于suanz的元素和右侧找到的小于suanz的元素进行交换
int suanz = nums[begin];
int i = begin, j = end;
while(i < j){
//从数组右侧向左扫描,将扫描到的不大于suanz的元素值赋值给第i个元素(begin或者上一次扫描到的大于suanz的元素所在位置)
while(i < j && suanz <= nums[j])j --;nums[i] = nums[j];
//从数组左侧向右扫描,将扫描到的不小于suanz的元素值赋值给第j个元素(上一次扫描到的小于suanz的元素所在位置)
while(i < j && suanz >= nums[i])i ++; nums[j] = nums[i];
}
//将suanz放到其应该所在位置
nums[i] = suanz;
//对于partition函数来说,输出应为i
将其用于快速排序(递归利用partition方法):
void quick_sort(vector<int> &nums){
if(nums.empty())return ;
quick_sort_RE(nums,0,nums.size() - 1);
cout << "快速排序结果为: ";
for(auto e:nums) cout << e << " ";cout << endl;
}
void quick_sort_RE(vector<int> &nums, int begin, int end){
if(begin >= end)return;
int suanz = nums[begin];
int i = begin, j = end;
while(i < j){
while(i < j && suanz <= nums[j])j --;nums[i] = nums[j];
while(i < j && suanz >= nums[i])i ++; nums[j] = nums[i];
}
nums[i] = suanz;
quick_sort_RE(nums,begin,i - 1);
quick_sort_RE(nums,i + 1,end);
}
将其用于寻找数组中最小的k个元素,(递归利用partition方法)
vector<int> k_partition(vector<int> &nums, int k){
vector<int> res;
if(k < 0)return res;
if(k > nums.size())return nums;
k_partition_RE(nums,k,0,nums.size() - 1);
res.assign(nums.begin(),nums.begin() + k);
return res;
}
void k_partition_RE(vector<int> &nums, int k, int begin, int end){
if(begin >= end)return;
int suanz = nums[begin];
int i = begin, j = end;
while(i < j){
while(i < j && suanz <= nums[j])j --;nums[i] = nums[j];
while(i < j && suanz >= nums[i])i ++; nums[j] = nums[i];
}
nums[i] = suanz;
if(i > k)k_partition_RE(nums,k, begin, i - 1);
else if(i < k)k_partition_RE(nums, k - i, i + 1, end);
else return;
return;
}