问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

PHP快速排序算法实现的原理及代码详解

发布网友 发布时间:2022-04-22 23:00

我来回答

2个回答

懂视网 时间:2022-04-06 04:46

php实现快速排序的方法:首先创建一个PHP示例文件;然后创建交换函数和主函数;接着对低子表和高子表进行递归排序;最后调用QuickSort算法即可。

推荐:《PHP视频教程》

基本思想:

快速排序(Quicksort)是对冒泡排序的一种改进。他的基本思想是:通过一趟排序将待排记录分割成独立的两部分,其中一部分的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行快速排序,整个排序过程可以递归进行,以达到整个序列有序的目的。

基本算法步骤:

举个栗子:
这里写图片描述

假如现在待排序记录是:

6 2 7 3 8 9

第一步、创建变量 $low 指向记录中的第一个记录,$high 指向最后一个记录,$pivot 作为枢轴赋值为待排序记录的第一个元素(不一定是第一个),这里:

$low = 0;
$high = 5;
$pivot = 6;

第二步、我们要把所有比 $pivot 小的数移动到 $pivot 的左面,所以我们可以开始寻找比6小的数,从 $high 开始,从右往左找,不断递减变量 $high 的值,我们找到第一个下标 3 的数据比 6 小,于是把数据 3 移到下标 0 的位置($low 指向的位置),把下标 0 的数据 6 移到下标 3,完成第一次比较:

3 2 7 6 8 9

//这时候,$high 减小为 3
$low = 0;
$high = 3;
$pivot = 6;

第三步、我们开始第二次比较,这次要变成找比 $pivot 大的了,而且要从前往后找了。递加变量 $low,发现下标 2 的数据是第一个比 $pivot 大的,于是用下标 2 ($low 指向的位置)的数据 7 和 指向的下标 3 ($high 指向的位置)的数据的 6 做交换,数据状态变成下表:

3 2 6 7 8 9

//这时候,$high 减小为 3
$low = 2;
$high = 3;
$pivot = 6;

完成第二步和第三步我们称为完成一个循环。

第四步(也就是开启下一个循环)、模仿第二步的过程执行。
第五步、模仿第三步的过程执行。

执行完第二个循环之后,数据状态如下:

3 2 6 7 8 9

//这时候,$high 减小为 3
$low = 2;
$high = 2;
$pivot = 6;

到了这一步,我们发现 $low 和 $high“碰头”了:他们都指向了下标 2。于是,第一遍比较结束。得到结果如下,凡是 $pivot(=6) 左边的数都比它小,凡是 $pivot 右边的数都比它大。

然后,对 、$pivot 两边的数据 {3,2} 和 {7,8,9},再分组分别进行上述的过程,直到不能再分组为止。

注意:第一遍快速排序不会直接得到最终结果,只会把比k大和比k小的数分到k的两边。为了得到最后结果,需要再次对下标2两边的数组分别执行此步骤,然后再分解数组,直到数组不能再分解为止(只有一个数据),才能得到正确结果。

算法实现:

//交换函数
function swap(array &$arr,$a,$b){
 $temp = $arr[$a];
 $arr[$a] = $arr[$b];
 $arr[$b] = $temp;
}

//主函数:
function QuickSort(array &$arr){
 $low = 0;
 $high = count($arr) - 1;
 QSort($arr,$low,$high);
}

主函数中,由于第一遍快速排序是对整个数组排序的,因此开始是 $low=0,$high=count($arr)-1。
然后 QSort() 函数是个递归调用过程,因此对它封装了一下:

function QSort(array &$arr,$low,$high){
 //当 $low >= $high 时表示不能再进行分组,已经能够得出正确结果了
 if($low < $high){
 $pivot = Partition($arr,$low,$high); //将$arr[$low...$high]一分为二,算出枢轴值
 QSort($arr,$low,$pivot - 1);	//对低子表($pivot左边的记录)进行递归排序
 QSort($arr,$pivot + 1,$high);	//对高子表($pivot右边的记录)进行递归排序
 }
}

从上面的 QSort()函数中我们看出,Partition()函数才是整段代码的核心,因为该函数的功能是:选取当中的一个关键字,比如选择第一个关键字。然后想尽办法将它放到某个位置,使得它左边的值都比它小,右边的值都比它大,我们将这样的关键字成为枢轴(pivot)。

直接上代码:

//选取数组当中的一个关键字,使得它处于数组某个位置时,左边的值比它小,右边的值比它大,该关键字叫做枢轴
//使枢轴记录到位,并返回其所在位置
function Partition(array &$arr,$low,$high){
 $pivot = $arr[$low]; //选取子数组第一个元素作为枢轴
 while($low < $high){ //从数组的两端交替向中间扫描(当 $low 和 $high 碰头时结束循环)
 while($low < $high && $arr[$high] >= $pivot){
  $high --;
 }
 swap($arr,$low,$high);	//终于遇到一个比$pivot小的数,将其放到数组低端

 while($low < $high && $arr[$low] <= $pivot){
  $low ++;
 }
 swap($arr,$low,$high);	//终于遇到一个比$pivot大的数,将其放到数组高端
 }
 return $low; //返回high也行,毕竟最后low和high都是停留在pivot下标处
}

组合起来的整个代码如下:

function swap(array &$arr,$a,$b){
 $temp = $arr[$a];
 $arr[$a] = $arr[$b];
 $arr[$b] = $temp;
}

function Partition(array &$arr,$low,$high){
 $pivot = $arr[$low]; //选取子数组第一个元素作为枢轴
 while($low < $high){ //从数组的两端交替向中间扫描
 while($low < $high && $arr[$high] >= $pivot){
  $high --;
 }
 swap($arr,$low,$high);	//终于遇到一个比$pivot小的数,将其放到数组低端
 while($low < $high && $arr[$low] <= $pivot){
  $low ++;
 }
 swap($arr,$low,$high);	//终于遇到一个比$pivot大的数,将其放到数组高端
 }
 return $low; //返回high也行,毕竟最后low和high都是停留在pivot下标处
}

function QSort(array &$arr,$low,$high){
 if($low < $high){
 $pivot = Partition($arr,$low,$high); //将$arr[$low...$high]一分为二,算出枢轴值
 QSort($arr,$low,$pivot - 1); //对低子表进行递归排序
 QSort($arr,$pivot + 1,$high); //对高子表进行递归排序
 }
}

function QuickSort(array &$arr){
 $low = 0;
 $high = count($arr) - 1;
 QSort($arr,$low,$high);
}

我们调用算法:

$arr = array(9,1,5,8,3,7,4,6,2);
QuickSort($arr);
var_dump($arr);

复杂度分析:

在最优的情况下,也就是选择数轴处于整个数组的中间值的话,则每一次就会不断将数组平分为两半。因此最优情况下的时间复杂度是 O(nlogn) (跟堆排序、归并排序一样)。

最坏的情况下,待排序的序列是正序或逆序的,那么在选择枢轴的时候只能选到边缘数据,每次划分得到的比上一次划分少一个记录,另一个划分为空,这样的情况的最终时间复杂度为 O(n^2).

综合最优与最差情况,平均的时间复杂度是 O(nlogn).

快速排序是一种不稳定排序方法。

由于快速排序是个比较高级的排序,而且被列为20世纪十大算法之一。。。。如此牛掰的算法,我们还有什么理由不去学他呢!

尽管这个算法已经很牛掰了,但是上面的算法程序依然有改进的地方。

热心网友 时间:2022-04-06 01:54

算法原理
下列动图来自五分钟学算法,演示了快速排序算法的原理和步骤。
步骤:
从数组中选个基准值
将数组中大于基准值的放同一边、小于基准值的放另一边,基准值位于中间位置
递归的对分列两边的数组再排序
代码实现
function
quickSort($arr)
{
$len
=
count($arr);
if
($len
<=
1)
{
return
$arr;
}
$v
=
$arr[0];
$low
=
$up
=
array();
for
($i
=
1;
$i
<
$len;
++$i)
{
if
($arr[$i]
>
$v)
{
$up[]
=
$arr[$i];
}
else
{
$low[]
=
$arr[$i];
}
}
$low
=
quickSort($low);
$up
=
quickSort($up);
return
array_merge($low,
array($v),
$up);
}
测试代码:
$startTime
=
microtime(1);
$arr
=
range(1,
10);
shuffle($arr);
echo
"before
sort:
",
implode(',
',
$arr),
"\n";
$sortArr
=
quickSort($arr);
echo
"after
sort:
",
implode(',
',
$sortArr),
"\n";
echo
"use
time:
",
microtime(1)
-
$startTime,
"s\n";
测试结果:
before
sort:
1,
7,
10,
9,
6,
3,
2,
5,
4,
8
after
sort:
1,
2,
3,
4,
5,
6,
7,
8,
9,
10
use
time:
0.0009009838104248s
时间复杂度
快速排序的时间复杂度在最坏情况下是O(N2),平均的时间复杂度是O(N*lgN)。
这句话很好理解:假设被排序的数列中有N个数。遍历一次的时间复杂度是O(N),需要遍历多少次呢?至少lg(N+1)次,最多N次。
1)
为什么最少是lg(N+1)次?快速排序是采用的分治法进行遍历的,我们将它看作一棵二叉树,它需要遍历的次数就是二叉树的深度,而根据完全二叉树的定义,它的深度至少是lg(N+1)。因此,快速排序的遍历次数最少是lg(N+1)次。
2)
为什么最多是N次?这个应该非常简单,还是将快速排序看作一棵二叉树,它的深度最大是N。因此,快读排序的遍历次数最多是N次。
您可能感兴趣的文章:PHP快速排序算法实例分析PHP四种排序算法实现及效率分析【冒泡排序,插入排序,选择排序和快速排序】PHP排序算法之快速排序(Quick
Sort)及其优化算法详解PHP递归实现快速排序的方法示例php
二维数组快速排序算法的实现代码PHP常用排序算法实例小结【基本排序,冒泡排序,快速排序,插入排序】PHP快速排序quicksort实例详解
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
高启强与陈书婷结婚是哪一集 陈舒婷和高启强第几集结婚 高启强陈书婷结婚是第几集 高启强和陈书婷结婚是第几集 高启强和陈书婷第几集结的婚 狂飙高启强第几集和大嫂在一起的 2021年清明节时间(是公历几月几号) js中类似`${xx,xxxy}`的语句是什么意思? 用支付宝帐号注册的淘宝帐号但是淘宝显示未绑定支付宝帐号如图 银行黑户影响子女什么 iphone 12价格下降幅度为什么这么大呢? 苹果行情20年来最差,你怎么看? php快速排序算法 苹果12元一斤,果农却面临销售难,钱都被谁赚走了? 冷库苹果销售遇“寒潮”,明年的苹果行情如何呢? php几种排序算法实例详解 卖1斤亏1元,苹果价格大跌滞销,这其中的因素有哪些? 苹果销售价格越来越两极分化,对此你怎么看? 苹果的价格还会往上走吗? 今年的苹果销量不行,这是为什么呢? 苹果价格大跌滞销,遭历史最严重行情,这是受哪些因素所影响? 我国苹果遭史上最严重行情,今年的苹果为何销售不出去? 隐形眼镜怎么用啊? 金立智能手机现在怎样? 配隐形眼镜 大概多少钱? 你觉得金立手机怎么样? 隐形眼镜有几种? 隐形眼镜的材质究竟是什么啊? 隐形眼镜哪个牌子好? 金立F40手机质量怎么样? 如何使用强大的PHP函数对数组进行排序 烟台苹果行情是怎样的? PHP中的快速排序算法如何实现倒序? php数组排序有很多的方法,哪位可以详细的分解一二吗,如用函数和不用函 ... 美国苹果股市一直都在上升的原因? PHP 怎么用冒泡算法进行排序呢 为什么不能用保温杯泡茶? 运用经济生活的知识预测苹果手机价格可能走势并说明理由 关于PHP冒泡排序法。 php数组随机排序几种方法 用保温杯泡茶好不好? 供求理论分析为什么苹果在消费旺季价格下降,海边别墅却在消费旺季价格上升 php中对一组数字从大到小排序方法 苹果市场价多少 年后,各地苹果行情如何? php如何按数组键值排序? 现在的苹果出口市场行情怎么样?求大神帮助 保温杯泡茶的危害到底有多大? PHP数组排序array_multisort函数详细用法跟排序方法是怎样的?_百度知 ... php冒泡排序法~呢?