快排的2种分区图解

主要是找分区点后把小于分区点值的放在左边,大于分区点的放在右边

关键点是如何找到这个分区点应该放的位置

分区方式1

选取最右边的3做分区点 privot

    把小于privot的放在左边
        按照同样的逻辑处理左边区间的数据
    把大于privot的放在右边
        按照同样的逻辑处理右边区间的数据

假设要把privot放在i的位置

  • 那么要有2个区间 ,最终实现的效果
    • [p,i-1]放小于privot的元素
    • [i+1,r] 放大于privot的元素
    • i 放pivot

arr[i]是第一个大于privot的,在i之后都是大于privot的,
    如果在遍历过程中发现了比privot小的数,
    要把这个数与arr[i] 交换,同时i++才能保证arr[i]是第一个大于privot的位置

遍历[p,r-1] 把小于分区点arr[r]的放入到[p,r-1]

最后把分区点挪到分区点索引i,并返回i

下面是1个分区过程图

代码如下

int partition(int arr[],int p,int r){
    int privot=arr[r];//分区点
    int i,j; //arr[p,i-1]为已处理区间
    i=p,j=p;
    for(;j<r-1;j++){
        if(arr[j]<privot){
            int tmp=arr[i];
            arr[i]=arr[j];
            arr[j]=tmp;
            i++;
        }
    }
    arr[r]=arr[i];
    arr[i]=privot;
    return i;
}

分区方式2

两端指针

把其中的一个挖出来,作为分隔点,这端就会有1个坑
从另外1端开始,考察元素 ,大于分隔点的挖出这个元素 移动到另外1端的坑处,
没坑的这端向中间移动,考察这端的元素与privot...具体看下图
总之就是
    1.挖坑
    2.对端考察(与privot比较)
        比较的结果是
                    1.向中央移动 
                            继续与privot比较
                    2.挖出来填到对端坑,对端向中央移动,考察 移动或者挖出

这种方式的分区代码
function partition1(&$arr,$left,$right){
    $privot=$arr[$right];

    while($left<$right) {

        while($arr[$left]<$privot && $left<$right){
            $left++;
        }
        if($arr[$left]>$privot  && $left<$right){
            $arr[$right]=$arr[$left];
            $right--;
        }
        while($arr[$right]>$privot && $left<$right){
            $right--;
        }
        if($arr[$right]<$privot  && $left<$right){
            $arr[$left]=$arr[$right];
            $left++;
        }
    }
    $arr[$left]=$privot;
    return $left;

}

在排序过程中 原有的大小顺序(456)被打乱,所以快排不是稳定排序算法

php快排完整代码

posted @ 2020-06-07 23:44  H&K  阅读(810)  评论(0编辑  收藏  举报