【数据结构】排序之快速排序

4 篇文章 0 订阅
3 篇文章 0 订阅

快速排序思路+代码

快速排序基本原理

可以看出,快排这个算法很狂啊,直接叫自己快速排序。
它的基本思想很简单,被称为分治思想

分治:即分而治之,即把一个问题转化成多个与其相似的小问题,再去研究小问题的解法。实现上,常常使用递归来实现

快速排序的基本思路是:找出一个基准点(称作pivot),通过某种方式的移动,将pivot左面变成都是小于等于pivot的元素,将其右面变成都是大于等于pivot的元素。
这样,就产生了一个以pivot为中心的,更加趋于有序的序列:
快速排序图解

再去对pivot的左半部分和右半部分进行相同的操作。

什么时候停止?

一个基本事实:只含有一个元素的序列是有序的序列。那么,如果进入本次递归的时候,序列只有一个元素,即标志元素pivot本身,就可以直接返回。

实现

实际在应用快速排序的时候,一般选取当前序列起始元素为pivot。
实现快速排序的时候有两种方式——交换法和挖坑法,两种方式大同小异。

挖坑法 操作如下:

首先:left=start;right=end;将arr[start]赋值给pivot,我们这里可以视为把arr[start]挖了出去,这个位置视为空的;

然后一个循环,条件为left<right;
循环内:
第一个循环,right从末尾开始往前寻找小于等于pivot的元素,如果找到,循环结束。如果满足left<right,把arr[right]赋值给arr[left](此时arr[left]是“空”的,相当于把arr[right]挖出,填到了arr[left])
此时,arr[right]视为空
第二个循环,left从头往后找大于等于pivot的元素,如果找到,循环结束。如果满足left<right,将arr[left]赋值给arr[right](相当于把arr[left]挖出去,填到了arr[right])
此时,arr[left]视为空

跳出循环后,一定有left==right成立,即二者重合,这个位置是“空”的,把pivot填进去。

递归左右序列

代码如下:

void Qsort(int arr[],int start,int end){
    if(start>=end)return;
    int left=start;
    int right=end;
    int pivot=arr[left];
    while(left<right){
        while (left<right&&arr[right]>=pivot)
            right--;
        if(left<right)arr[left]=arr[right];
        while(left<right&&arr[left]<=pivot)
            left++;
        if(left<right)arr[right]=arr[left];
    }
    arr[left]=pivot;
    Qsort(arr, start, left-1);
    Qsort(arr, left+1, end);
}

交换法
前提条件:有一数组arr[],当前序列起始下标为start,终止下标为end。

步骤具体操作
第一步:选取start位置的元素为pivot;初始化left为start,right为end+1;
第二步:当left<right,就进入循环
第二步①:left++;当 left≤end 并且 arr[left]≤pivot的时候,left++;.
第二步②:right–;当arr[right]>pivot的时候,right–;
第二步③:两个循环终止的时候,比较一下left和right,若满足left<right,交换arr[left]和arr[right];
第三步:交换arr[start]和arr[right]。(将pivot挪到中间)
第四步:递归左右序列

Q:第二步中,为什么要先进行对left和right进行加减,而不是后面进行?
A:因为我们想要获得right最后停留的位置,那是pivot要换到的位置。

Q:为什么right不直接赋值end,而是要先+1后-1?
A:因为第二步的时候需要先对left和right进行加减。

代码如下:

void swap(int& a,int& b){
    int c=a;
    a=b;
    b=c;
}
void Qsort(int arr[],int start,int end){
    if(start>=end)return;//递归出口
    int left=start;
    int right=end+1;
    int pivot=arr[left];//选取基准
    while (left<right)//当left在right前面就进入循环
    {
        /*left和right不直接赋值start+1和end的原因:对left和right的加减操作需要放在循环之前*/
        /*加减操作在前面的原因:要获取right最终停留的位置*/
        left++;
        while (left<=end && arr[left]<=pivot)
            left++;
        right--;
        while(arr[right]>pivot)
            right--;
        if(left<right)//如果没有越界,就交换
            swap(arr[left],arr[right]);
    }
    swap(arr[start],arr[right]);//把pivot换到中间去
    Qsort(arr, start,right-1);//递归左右序列
    Qsort(arr, right+1, end);
}

随便敲点数据进去:

测试数据1
测试数据2

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值