快速排序与三向切分的快速排序

  • 快速排序
  • 三向切分的快速排序
快速排序

讲解的十分生动形象
维护一个指针lo,维护一个指针hi,初始时lo指向数组的第一个元素,hi指向数组的最后一个元素。
对于快速排序来说其核心有如下几点
1. 选取一个元素(一般为数组的第一个元素)作为基准,可以生动的想象在基准元素上挖了一个坑,把基准元素挖了出来,并移植给了临时变量x
2. 既然将基准元素挖坑并取走那还需要把这个坑给填上,所以就从数组尾端向前遍历,直到遇到第i个位置的元素小于基准元素x,这时候就可以把第i个位置的元素挖走,并放到之前被挖走元素的位置上。(挖走只是形象的说法,其实该位置元素并没有物理上的变化,只是覆盖的过程)
3. 当经过第2步后第一步被挖走的位置已经被第二步挖来的元素填充,所以可以继续向后移动lo指针,直到遇到一个j位置使得j位置的元素大于x元素,将j位置挖走,放到第二步中空缺的位置处。
4. 直到lo和hi重合完成一次遍历,将x元素值填到此时的lo指针指向的位置,因为如果把上述步骤想象成挖坑填坑的话,当lo与hi重合的位置一定是最后一个需要填坑的位置,并且lo之前的值都小于等于x,之后的值都大于等于x
5. 递归执行。

   public void sort(int []nums,int lo,int high){
           if(lo>=high){//如果递归到子数组不存在元素时返回

               return;

           }
            int x=nums[lo];
            int begin=lo;
            int end=high;
            while(lo<high){

                while(lo<high && nums[high]>=x){
                    high--;
                }
                if(lo<high){
                    nums[lo++]=nums[high];
                }
                while(lo<high && nums[lo]<=x){
                    lo++;
                }
                if(lo<high){
                    nums[high--]=nums[lo];
                }

            }

            nums[lo]=x;
            sort(nums,begin,lo-1);
            sort(nums,lo+1,end);
       }
三向切分的快排

快速排序的改进一般基于如下两点:
1. 当数组的规模较小时,快速排序的效率不如插入排序,因此当递归到数组规模较小时可以进行插入排序
修改代码为:
将:

if(lo>=high){
    return;
}

修改为:

if(hi<=lo+M){
    Insertion.sort(a,lo,high);
    return;
}

2.对于存在大量重复元素的时候,可以采用三向切分的方式
其主要过程如下:
从左到右遍历一次,维护一个指针lt,使得a[lo,lt-1]的元素都小于v,
维护一个指针gt,使得a[gt+1,hi]的元素都大于v,
维护一个指针i,使得a[lt,i-1]的元素都等于v,
a[i,gt]的元素为还未参加排序的元素
如果a[i] < v 将a[i]与a[lt]元素进行交换,
并将lt和i都加一
如果a[i]>v 将a[gt]与a[i]进行交换,并将gt减一,因为换过了的元素不一定比v大所以不能将i加一
如果a[i]=v,则将i++

代码如下:

public void sort(int []a,int lo,int hi){
        if(lo>=hi){
            return;
        }
        int lt=lo;
        int i=lo+1;
        int gt=hi;
        int x=a[lo];
        while(i<=gt){
            if(a[i]<x){
                int tmp=a[lt];
                a[lt]=a[i];
                a[i]=tmp;
                lt++;
                i++;
            }
            if(a[i]>x){
                int tmp=a[gt];
                a[gt]=a[i];
                a[i]=tmp;
                gt--;
            }
            if(a[i]==x){
                i++;
            }
        }
    sort(a,lo,lt-1);
    sort(a,gt+1,lt);
    }
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值