#快速排序

快排基本思想-快排是一种交换排序,是一种二叉树结构的排序方法,采用分治递归的思想;从待排序数组中取一个数,称为key/pivot-基数,遍历数组将比key大的数字放在key的右边,将比key小的数字放在key的左边,遍历完成后,数组被分成了左右两个区域,将左右两个区域视为两个数组,重复前两个步骤,直到排序完成

将区间按照key划分为左右两部分的方法:
1.左右指针法
//左右指针法
int partsort1(vector<int>&nums, int left, int right){
        int mid = getmid(nums, left, right);
        swap(nums[right], nums[mid]);
        int key = nums[right];
        int keyindex = right;
        while (left < right){
               while (left < right&&nums[left] <= key){
                       left++;
               }
               while (left < right&&nums[right] >= key){
                       right--;
               }
               swap(nums[left], nums[right]);
        }
        swap(nums[left], nums[keyindex]);
        return left;
}

2.挖坑法
//挖坑法
int partsort2(vector<int>&nums, int left, int right){
        int mid = getmid(nums, left, right);
        swap(nums[right], nums[mid]);
        int key = nums[right];
        while (left < right){
               while (left < right&&nums[left] <= key){
                       left++;
               }
               nums[right] = nums[left];
               while (left < right&&nums[right] >= key){
                       right--;
               }
               nums[left] = nums[right];
        }
        nums[left] = key;
        return left;
}

3.前后指针法
//前后指针法
int partsort3(vector<int>&nums, int left, int right){
        int prev = left - 1;
        int cur = left;
        int mid = getmid(nums, left, right);
        swap(nums[right], nums[mid]);
        int key = nums[right];
        while (cur < right){
               if (nums[cur] < key&&prev++ != cur){
                       swap(nums[prev], nums[cur]);
               }
               cur++;
        }
        prev++;
        swap(nums[prev], nums[right]);
        return prev;
}


快排什么时候最坏?- 有序的情况下
最坏情况的优化?- 三数取中法选key
int getmid(vector<int>&nums, int left, int right){
               int mid = (left + right) >> 1;
               //1-left<mid
               if (nums[left] < nums[mid]){
                       //1.1-right left mid
                       if (nums[right] < nums[left]){
                              return left;
                              //1.2-left mid right
                       }
                       else if (nums[mid] < nums[right]){
                              return mid;
                       }
                       else{//1.3-left right mid
                              return right;
                       }
               }
               else{//2-mid<left
                       //2.1-right mid left
                       if (nums[right] < nums[mid]){
                              return mid;
                              //2.2-mid left right
                       }
                       else if (nums[left] < nums[right]){
                              return left;
                       }
                       else{//2.3-mid right left
                              return right;
                       }
               }
        }


快排非递归-用stack栈
递归-调用太多导致开辟栈帧太多-栈溢出
非递归-用栈-在堆上开辟空间-非递归借助栈达到递归
class Solution {
public:
        int partsort2(vector<int>&nums, int left, int right){
               int key = nums[right];
               while (left < right){
                       while (left < right&&nums[left] <= key){
                              left++;
                       }
                       //左边坑出来了
                       nums[right] = nums[left];
                       while (left < right&&nums[right] >= key){
                              right--;
                       }
                       //右边坑出来了
                       nums[left] = nums[right];
               }
               nums[left] = key;
               return left;
        }
        void quicksortstack(vector<int>&nums, int left, int right){
               stack<int>st;
               st.push(left);
               st.push(right);
               while (!st.empty()){
                       int right = st.top();
                       st.pop();
                       int left = st.top();
                       st.pop();
                       int pos = partsort2(nums, left, right);
                       if (left < pos - 1){
                              st.push(left);
                              st.push(pos - 1);
                       }
                       if (pos + 1 < right){
                              st.push(pos + 1);
                              st.push(right);
                       }
               }
        }
        vector<int> sortArray(vector<int>& nums) {
               int left = 0;
               int right = nums.size() - 1;
               quicksortstack(nums, left, right);
               return nums;
        }
};


快排特性
不稳定
时间复杂度nlogn
空间复杂度1
class Solution {
public:
        int partsort2(vector<int>&nums, int left, int right){
               int key = nums[right];
               while (left < right){
                       while (left < right&&nums[left] <= key){
                              left++;
                       }
                       //左边坑出来了
                       nums[right] = nums[left];
                       while (left < right&&nums[right] >= key){
                              right--;
                       }
                       //右边坑出来了
                       nums[left] = nums[right];
               }
               nums[left] = key;
               return left;
        }
        void quicksort(vector<int>&nums, int left, int right){
               //递归终止条件
               if (left >= right){
                       return;
               }
               int pos = partsort2(nums, left, right);
               quicksort(nums, left, pos - 1);
               quicksort(nums, pos + 1, right);
        }
        vector<int> sortArray(vector<int>& nums) {
               int left = 0;
               int right = nums.size() - 1;
               quicksort(nums, left, right);
               return nums;
        }
};

测试用例- [6,1,2,7,9,3,4,5,10,8]
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值