partition方法,及利用其进行快速排序,输出最小的k个值等操作

partition算法

partition算法就是把数组分割成几部分,对于快速排序中的分割算法就是把数组分割成大于某个数的一部分和小于一个数的一部分

partition方法从目的上看是达到以下三点:

  1. 选中数组中某一个元素,即为suanz(可以是任意点,可以选起始点,终止点,或者中间任意一个点);
  2. 扫描整个数组,凡是小于suanz的全部放到数组左端,大于suanz的放到数组的右端;
  3. 最后将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;
    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值