php实现快速排序

1.快速排序的概念

随机找出一个数(通常就拿数组的第一个数就行),把它插入一个位置,使得它左边的数都比它小,右边的数都比它大,这样就将一个数组分成了两个子数组,然后在按照同样的方法把子数组分成更小的子数组,直到不能分解为止。用比较通俗的话:挖坑填数+分而治之。

2.图解分析

取第一个数作为基准数,这是low=0,high=8,target=arr[0]=12,由于已经将arr[0]保存到变量target中,可以理解成在数组arr[0]上挖了一个坑,那就需要将这个坑填上,从high=8开始向后扫描,遇到一个比target小的数,arr[8]就符合,用arr[8]这个数将arr[0]这个坑填上,arr[0]=arr[8];arr[8]又出现了坑,就需要从low=1开始由左向右扫描,找一个比target=12大的数,arr[1]就符合,将arr[8]的这个坑用arr[1]填上,arr[8]=arr[1];arr[1]出现了坑,需要从high=7开始向左扫描,找一个比target=12小的数,arr[7]填上arr[1],arr[1] = arr[7];在由low=2开始向右扫描,找一个比target=12大的数,arr[2]填上arr[7],arr[7]=arr[2]......直到high=low,将目标数填上最后的这个坑,arr[high]=target,这样就变成了

用target=12将数组分成了两个子数组,分别对这两个子数组进行上面的操作。

3.代码实现

 

//找到要插入的位置
function findPos(&$arr, $low, $high) {
    $target = $arr[$low];   //  将目标数存起来
    while ($low < $high) {
        //从右向左找小于target的数
        while ($low < $high && $arr[$high] >= $target) {
            $high--;
        }
        $arr[$low] = $arr[$high];   //将arr[high]填到arr[low]中
        //从左向右找大于target的数
        while ($low < $high && $arr[$low] <= $target) {
            $low++;
        }
        $arr[$high] = $arr[$low];   //将arr[low]填到arr[high]中
    }
    $arr[$high] = $target;  //此时low=high,将目标数填入这个坑中
    return $high;
}

function quitSort(&$arr,$low,$high){
    $pos = findPos($arr, $low, $high);
    if ($low<$pos-1){
        quitSort($arr,$low,$pos-1);
    }
    if ($pos+1 < $high){
        quitSort($arr,$pos+1,$high);
    }
}
$arr = [12,56,98,32,16,34,2,9,1];
$len = count($arr);
quitSort($arr,0,$len-1);
dump($arr);

 

4.效果展示

 


 

5.效率分析

 ①快排的一个关键因素是选好枢轴,它进行一趟排序后,枢轴元素在表中的位置被唯一确定下来,且枢轴元素将待排序列分成两个子序列,左边的序列中的元素都比 枢轴元素小,右边的序列都比枢轴元素大。然后,分别在左右序列中选择枢轴元素再开始排序,因而,快排中包含了递归。
 ②当待排的元素初始有序时,快排的性能大大地下降。因为此时枢轴划分的子序列严重地不对称(一般选择第一个元素作为枢轴记录),快排退化为冒泡排序。
③快排是不稳定的,因为在排序过程中,设置了两个指针 low 和 high 。首先从high 开始自减,寻找第一个比枢轴小的元素,并将之与枢轴记录进行交换,这种跳跃式的交换可能会造成元素的相对位置的改变。
 ④对于快排而言,元素的初始序列与排序的趟数和比较次数是有关的。但是,平均情况下,对于内部排序而言,快排的性能是最好。平均时间复杂度为 O(n^2),空间复杂度为O(logn)。

效果展示来自http://blog.jobbole.com/11745/

 

 

 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值