浅谈快速排序--从三色旗问题到

首先我们先来了解下快速排序的时间复杂度和稳定性分析,

快速排序的时间复杂度平均为o(n*logn)最优情况为o(n*logn)最差情况为o(n^2)

稳定性为不稳定的

然后让我们正式开始分析快速排序

首先我们要了解快速排序就要先理解三色旗问题:

有一条绳子上面挂有白、红、蓝三种颜色的多面旗子,这些旗子的排列是无序的。现在要将绳子上的旗子按蓝、白、红三种颜色进行归类排列,但是只能在绳子上进行旗子的移动,并且每次只能调换两个旗子。问如何采用最少的步骤来完成三色旗的排列呢?

对于这种问题我们就可以将0代表蓝色,1代表白色,2代表红色,放到数组里面进行排序,我们可以采用双指针,将蓝色全放到白色左面,红色全放到白色右面。接下来看下三色旗问题的解决代码

class Solution {
public:
    void sortColors(vector<int>& nums) {
        int left = 0-1,right = nums.size(),i = 0;//将left和right这么定义是为了下面快排处理边界值问题
        while(i<right)
        {
            if(nums[i]>1)
            {swap(nums[i],nums[--right]);//因为不能保证换过来的不是2所以此时i不能++
            }
            else if(nums[i]<1)
            {
            swap(nums[i++],nums[++left]);
            }
            else if(nums[i]==1){
                i++;
            }
        }
        
    }
};

此代码为力扣75.颜色分类的通过代码

可以看出三色旗的思想就是确定一个基准值,再将小于基准值的交换到基准值左面,将大于基准值交换到基准值右面

 

接下来我们带着三色旗的思想来看快速排序的代码

#include <iostream>
#include <vector>
using namespace std;
pair<int, int>Quick(vector<int>&nums,int L,int R)//将排序好的左右边界返回
{
	int temp = nums[L];
	int i = L - 1, j = R + 1,index = L;
	while (index < j)
	{
		if(nums[index]>temp)
		{
			swap(nums[index], nums[--j]);
		}
		else if (nums[index] < temp)
		{
			swap(nums[index++], nums[++i]);
		}
		else if(nums[index] == temp)
		{
			index++;
		}
	}
	return make_pair(i, j);
}
void Quick_sort(vector<int>&nums,int L,int R)
{
	if(L>=R)return;

	pair<int,int>a = Quick(nums, L, R);
    //递归利用pair返回的左右边界,再将左右边界的子数组进行排序
	Quick_sort(nums, L, a.first);
	Quick_sort(nums, a.second, R);
}
void main()
{
	vector<int>nums = { 5,6,4,3,2 };
	Quick_sort(nums, 0, nums.size() - 1);
	for (int it : nums)
	{
		cout << it << " ";
	}
}

接下来我们以56432这个数组来举例

 我们确定当前这次排序基准值为5,i和j的值最开始在数组的两边,目前nums[index]=temp执行index++;

 此时nums[index]=6>temp,我们把6交换到数组右面;

 接下来再看交换过来的数的大小1,发现此时<temp,我们把这个数交换到左边;

 4也一样交换到左边

 3也交换到左边

 此时此次排序结束,我们发现当前数组最后排序的结果为24356,和最后结果23456,虽然整个数组的顺序没对,但是我们发现5的相对位置对了,接下来我们只要通过递归,将5的左右子数组进行排序,最后一定可以得到一个正确的顺序。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值