首页 后端开发 php教程 php实现几种常见的排序算法

php实现几种常见的排序算法

Mar 10, 2018 pm 01:34 PM
php 排序 算法

交换排序:交换排序的基本思想是,比较两个记录键值的大小,如果这两个记录键值的大小出现逆序,则交换这两个记录,这样将键值较小的记录向序列前部移动,键值较大的记录向序列后部移动。




一、冒泡排序        

介绍:

冒泡排序(Bubble Sort,台湾译为:泡沫排序或气泡排序)是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。

步骤:

  1. 比较相邻的元素。如果第一个比第二个大,就交换他们两个。

  2. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。

  3. 针对所有的元素重复以上的步骤,除了最后一个。

  4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

冒泡排序理解起来是最简单,但是时间复杂度(O(n^2))也是最大的之一,实现代码如下:

<br/>
登录后复制
登录后复制
登录后复制
  1. $arr=array(1,43,54,62,21,66,32,78,36,76,39);

  2. function getpao($arr)

  3. {

  4. $len=count($arr);

  5. //设置一个空数组 用来接收冒出来的泡

  6. //该层循环控制 需要冒泡的轮数

  7. for($i=1;$i<$len;$i++)

  8. { //该层循环用来控制每轮 冒出一个数 需要比较的次数

  9. for($k=0;$k<$len-$i;$k++)

  10. {

  11. if($arr[$k]>$arr[$k+1])

  12. {

  13. $tmp=$arr[$k+1];

  14. $arr[$k+1]=$arr[$k];

  15. $arr[$k]=$tmp;

  16. }

  17. }

  18. }

  19. return $arr;

  20. }

二、快速排序

介绍:

快速排序是由东尼·霍尔所发展的一种排序算法。在平均状况下,排序 n 个项目要Ο(n log n)次比较。在最坏状况下则需要Ο(n2)次比较,但这种状况并不常见。事实上,快速排序通常明显比其他Ο(n log n) 算法更快,因为它的内部循环(inner loop)可以在大部分的架构上很有效率地被实现出来,且在大部分真实世界的数据,可以决定设计的选择,减少所需时间的二次方项之可能性。

步骤:

  1. 从数列中挑出一个元素,称为 “基准”(pivot),

  2. 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。

  3. 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。

快排也是一个高效的排序算法,它的时间复杂度也是O(nlogn)。代码如下:

  1. function quick_sort($arr) {

  2. //先判断是否需要继续进行

  3. $length = count($arr);

  4. if($length <= 1) {

  5. return $arr;

  6. }

  7. //如果没有返回,说明数组内的元素个数 多余1个,需要排序

  8. //选择一个标尺

  9. //选择第一个元素

  10. $base_num = $arr[0];

  11. //遍历 除了标尺外的所有元素,按照大小关系放入两个数组内

  12. //初始化两个数组

  13. $left_array = array();//小于标尺的

  14. $right_array = array();//大于标尺的

  15. for($i=1; $i<$length; $i++) {

  16. if($base_num > $arr[$i]) {

  17. //放入左边数组

  18. $left_array[] = $arr[$i];

  19. } else {

  20. //放入右边

  21. $right_array[] = $arr[$i];

  22. }

  23. }

  24. //再分别对 左边 和 右边的数组进行相同的排序处理方式

  25. //递归调用这个函数,并记录结果

  26. $left_array = quick_sort($left_array);

  27. $right_array = quick_sort($right_array);

  28. //合并左边 标尺 右边

  29. return array_merge($left_array, array($base_num), $right_array);

  30. }

选择排序

选择排序包括两种,分别是直接选择排序和堆排序,选择排序的基本思想是每一次在n-i+1(i=1,2,3,...,n-1)个记录中选取键值最小的记录作为有序序列的第i个记录

三、选择排序

介绍:

选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理如下。首先在未排序序列中找到最小元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小元素,然后放到排序序列末尾。以此类推,直到所有元素均排序完毕。

<br/>

选择排序理解起来也比较简单,时间复杂度也是O(n^2),实现代码如下:

<br/>
登录后复制
登录后复制
登录后复制

<br/>

[php] view plain copy

<br/>

  1. function select_sort($arr) {

  2. //实现思路 双重循环完成,外层控制轮数,当前的最小值。内层 控制的比较次数

  3. //$i 当前最小值的位置, 需要参与比较的元素

  4. for($i=0, $len=count($arr); $i<$len-1; $i++) {

  5. //先假设最小的值的位置

  6. $p = $i;

  7. //$j 当前都需要和哪些元素比较,$i 后边的。

  8. for($j=$i+1; $j<$len; $j++) {

  9. //$arr[$p] 是 当前已知的最小值

  10. if($arr[$p] > $arr[$j]) {

  11. //比较,发现更小的,记录下最小值的位置;并且在下次比较时,

  12. // 应该采用已知的最小值进行比较。

  13. $p = $j;

  14. }

  15. }

  16. //已经确定了当前的最小值的位置,保存到$p中。

  17. //如果发现 最小值的位置与当前假设的位置$i不同,则位置互换即可

  18. if($p != $i) {

  19. $tmp = $arr[$p];

  20. $arr[$p] = $arr[$i];

  21. $arr[$i] = $tmp;

  22. }

  23. }

  24. //返回最终结果

  25. return $arr;

  26. }

四、堆排序 <br/>

介绍:

堆积排序(Heapsort)是指利用这种数据结构所设计的一种排序算法。堆是一个近似完全二叉树的结构,并同时满足堆性质:即子结点的键值或索引总是小于(或者大于)它的父节点。

步骤:

堆排序是指利用堆积树(堆)这种数据结构所设计的一种排序算法,利用数组的特点快速定位指定索引的元素。堆分为大根堆和小根堆,是完全二叉树。大根堆的要求是每个节点的值都不大于其父节点的值,即A[PARENT[i]] >= A[i]。在数组的非降序排序中,需要使用的就是大根堆,因为根据大根堆的要求可知,最大的值一定在堆顶。

排序效果:

<br/>

堆排序是一种高效的排序算法,它的时间复杂度是O(nlogn)。原理是:先把数组转为一个最大堆,然后把第一个元素跟第i元素交换,然后把剩下的i-1个元素转为最大堆,然后再把第一个元素与第i-1个元素交换,以此类推。实现代码如下:

function heapSort($arr) {
    $len = count($arr);    // 先建立最大堆
    for ($i = floor(($len - 1) / 2); $i >= 0; $i--) {        $s = $i;        $childIndex = $s * 2 + 1;        while ($childIndex < $len) {            // 在父、左子、右子中 ,找到最大的
            if ($childIndex + 1 < $len && $arr[$childIndex] < $arr[$childIndex + 1]) $childIndex++;            if ($arr[$s] < $arr[$childIndex]) {                $t = $arr[$s];                $arr[$s] = $arr[$childIndex];                $arr[$childIndex] = $t;                $s = $childIndex;                $childIndex = $childIndex * 2 + 1;
            } else {                break;
            }
        }
    }    // 从最后一个元素开始调整
    for ($i = $len - 1; $i > 0; $i--) {        $t = $arr[$i];        $arr[$i] = $arr[0];        $arr[0] = $t;        // 调整第一个元素
        $s = 0;        $childIndex = 1;        while ($childIndex < $i) {            // 在父、左子、右子中 ,找到最大的
            if ($childIndex + 1 < $i && $arr[$childIndex] < $arr[$childIndex + 1]) $childIndex++;            if ($arr[$s] < $arr[$childIndex]) {                $t = $arr[$s];                $arr[$s] = $arr[$childIndex];                $arr[$childIndex] = $t;                $s = $childIndex;                $childIndex = $childIndex * 2 + 1;
            } else {                break;
            }
        }
    }    return $arr;
}$arr = [3,1,13,5,7,11,2,4,14,9,15,6,12,10,8];
print_r(bubbleSort($arr));
登录后复制
  • <br/>

<br/>

插入排序

五、插入排序

介绍:

插入排序(Insertion Sort)的算法描述是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,通常采用in-place排序(即只需用到O(1)的额外空间的排序),因而在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。

步骤:

  1. 从第一个元素开始,该元素可以认为已经被排序

  2. 取出下一个元素,在已经排序的元素序列中从后向前扫描

  3. 如果该元素(已排序)大于新元素,将该元素移到下一位置

  4. 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置

  5. 将新元素插入到该位置中

  6. 重复步骤2

<br/>感觉插入排序跟冒泡排序有点相似,时间复杂度也是O(n^2),实现代码如下:

<br/>

[php] view plain copy

<br/>

  1. function insert_sort($arr) {

  2. //区分 哪部分是已经排序好的

  3. //哪部分是没有排序的

  4. //找到其中一个需要排序的元素

  5. //这个元素 就是从第二个元素开始,到最后一个元素都是这个需要排序的元素

  6. //利用循环就可以标志出来

  7. //i循环控制 每次需要插入的元素,一旦需要插入的元素控制好了,

  8. //间接已经将数组分成了2部分,下标小于当前的(左边的),是排序好的序列

  9. for($i=1, $len=count($arr); $i<$len; $i++) {

  10. //获得当前需要比较的元素值。

  11. $tmp = $arr[$i];

  12. //内层循环控制 比较 并 插入

  13. for($j=$i-1;$j>=0;$j--) {

  14. //$arr[$i];//需要插入的元素; $arr[$j];//需要比较的元素

  15. if($tmp < $arr[$j]) {

  16. //发现插入的元素要小,交换位置

  17. //将后边的元素与前面的元素互换

  18. $arr[$j+1] = $arr[$j];

  19. //将前面的数设置为 当前需要交换的数

  20. $arr[$j] = $tmp;

  21. } else {

  22. //如果碰到不需要移动的元素

  23. //由于是已经排序好是数组,则前面的就不需要再次比较了。

  24. break;

  25. }

  26. }

  27. }

  28. //将这个元素 插入到已经排序好的序列内。

  29. //返回

  30. return $arr;

  31. }

<br/>
登录后复制
登录后复制
登录后复制

六、希尔排序

介绍:

希尔排序,也称递减增量排序算法,是插入排序的一种高速而稳定的改进版本。

希尔排序是基于插入排序的以下两点性质而提出改进方法的:

1、插入排序在对几乎已经排好序的数据操作时, 效率高, 即可以达到线性排序的效率

2、但插入排序一般来说是低效的, 因为插入排序每次只能将数据移动一位>

排序效果:

<br/>希尔排序其实可以理解是插入排序的一个优化版,它的效率跟增量有关,增量要取多少,根据不同的数组是不同的,所以希尔排序是一个不稳定的排序算法,它的时间复杂度为O(nlogn)到O(n^2)之间,实现代码如下:

function shellSort($arr) {
    $len = count($arr);    $stepSize = floor($len / 2);    while ($stepSize >= 1) {        for ($i = $stepSize; $i < $len; $i++) {            if ($arr[$i] < $arr[$i - $stepSize]) {                $t = $arr[$i];                $j = $i - $stepSize;                while ($j >= 0 && $t < $arr[$j]) {                    $arr[$j + $stepSize] = $arr[$j];                    $j -= $stepSize;
                }                $arr[$j + $stepSize] = $t;
            }
        }        // 缩小步长,再进行插入排序
        $stepSize = floor($stepSize / 2);
    }    return $arr;
}$arr = [3,1,13,5,7,11,2,4,14,9,15,6,12,10,8];
print_r(bubbleSort($arr));
登录后复制

<br/>

七、归并排序

介绍:

归并排序(Merge sort,台湾译作:合并排序)是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(pide and Conquer)的一个非常典型的应用

步骤:

  1. 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列

  2. 设定两个指针,最初位置分别为两个已经排序序列的起始位置

  3. 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置

  4. 重复步骤3直到某一指针达到序列尾

  5. 将另一序列剩下的所有元素直接复制到合并序列尾

排序效果:

<br/>归并排序的时间复杂度也是O(nlogn)。原理是:对于两个排序好的数组,分别遍历这两个数组,获取较小的元素插入新的数组中,那么,这么新的数组也会是排序好的。代码如下:

我们先来看看主函数部分:

//交换函数function swap(array &$arr,$a,$b){
    $temp = $arr[$a];    $arr[$a] = $arr[$b];    $arr[$b] = $temp;
}//归并算法总函数function MergeSort(array &$arr){
    $start = 0;    $end = count($arr) - 1;
    MSort($arr,$start,$end);
}
登录后复制

在总函数中,我们只调用了一个 MSort() 函数,因为我们要使用递归调用,所以将 MSort() 封装起来。

下面我们来看看 MSort() 函数:

function MSort(array &$arr,$start,$end){    //当子序列长度为1时,$start == $end,不用再分组    if($start < $end){        $mid = floor(($start + $end) / 2);	//将 $arr 平分为 $arr[$start - $mid] 和 $arr[$mid+1 - $end]        MSort($arr,$start,$mid);			//将 $arr[$start - $mid] 归并为有序的$arr[$start - $mid]        MSort($arr,$mid + 1,$end);			//将 $arr[$mid+1 - $end] 归并为有序的 $arr[$mid+1 - $end]        Merge($arr,$start,$mid,$end);       //将$arr[$start - $mid]部分和$arr[$mid+1 - $end]部分合并起来成为有序的$arr[$start - $end]
    }
}
登录后复制

上面的 MSort() 函数实现将数组分半再分半(直到子序列长度为1),然后将子序列合并起来。

现在是我们的归并操作函数 Merge() :

//归并操作function Merge(array &$arr,$start,$mid,$end){
    $i = $start;    $j=$mid + 1;    $k = $start;    $temparr = array();    while($i!=$mid+1 && $j!=$end+1)
    {       if($arr[$i] >= $arr[$j]){           $temparr[$k++] = $arr[$j++];
       }       else{           $temparr[$k++] = $arr[$i++];
       }
    }    //将第一个子序列的剩余部分添加到已经排好序的 $temparr 数组中
    while($i != $mid+1){        $temparr[$k++] = $arr[$i++];
    }    //将第二个子序列的剩余部分添加到已经排好序的 $temparr 数组中
    while($j != $end+1){        $temparr[$k++] = $arr[$j++];
    }    for($i=$start; $i<=$end; $i++){        $arr[$i] = $temparr[$i];
    }
}
登录后复制

到了这里,我们的归并算法就完了。我们调用试试:

$arr = array(9,1,5,8,3,7,4,6,2);
MergeSort($arr);
var_dump($arr);
登录后复制

相关推荐:

php冒泡、选择、插入和快速排序算法分享

PHP多维数组排序算法分析

PHP排序算法系列之直接选择排序详解

以上是php实现几种常见的排序算法的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

适用于 Ubuntu 和 Debian 的 PHP 8.4 安装和升级指南 适用于 Ubuntu 和 Debian 的 PHP 8.4 安装和升级指南 Dec 24, 2024 pm 04:42 PM

PHP 8.4 带来了多项新功能、安全性改进和性能改进,同时弃用和删除了大量功能。 本指南介绍了如何在 Ubuntu、Debian 或其衍生版本上安装 PHP 8.4 或升级到 PHP 8.4

我后悔之前不知道的 7 个 PHP 函数 我后悔之前不知道的 7 个 PHP 函数 Nov 13, 2024 am 09:42 AM

如果您是一位经验丰富的 PHP 开发人员,您可能会感觉您已经在那里并且已经完成了。您已经开发了大量的应用程序,调试了数百万行代码,并调整了一堆脚本来实现操作

如何设置 Visual Studio Code (VS Code) 进行 PHP 开发 如何设置 Visual Studio Code (VS Code) 进行 PHP 开发 Dec 20, 2024 am 11:31 AM

Visual Studio Code,也称为 VS Code,是一个免费的源代码编辑器 - 或集成开发环境 (IDE) - 可用于所有主要操作系统。 VS Code 拥有针对多种编程语言的大量扩展,可以轻松编写

在PHP API中说明JSON Web令牌(JWT)及其用例。 在PHP API中说明JSON Web令牌(JWT)及其用例。 Apr 05, 2025 am 12:04 AM

JWT是一种基于JSON的开放标准,用于在各方之间安全地传输信息,主要用于身份验证和信息交换。1.JWT由Header、Payload和Signature三部分组成。2.JWT的工作原理包括生成JWT、验证JWT和解析Payload三个步骤。3.在PHP中使用JWT进行身份验证时,可以生成和验证JWT,并在高级用法中包含用户角色和权限信息。4.常见错误包括签名验证失败、令牌过期和Payload过大,调试技巧包括使用调试工具和日志记录。5.性能优化和最佳实践包括使用合适的签名算法、合理设置有效期、

您如何在PHP中解析和处理HTML/XML? 您如何在PHP中解析和处理HTML/XML? Feb 07, 2025 am 11:57 AM

本教程演示了如何使用PHP有效地处理XML文档。 XML(可扩展的标记语言)是一种用于人类可读性和机器解析的多功能文本标记语言。它通常用于数据存储

php程序在字符串中计数元音 php程序在字符串中计数元音 Feb 07, 2025 pm 12:12 PM

字符串是由字符组成的序列,包括字母、数字和符号。本教程将学习如何使用不同的方法在PHP中计算给定字符串中元音的数量。英语中的元音是a、e、i、o、u,它们可以是大写或小写。 什么是元音? 元音是代表特定语音的字母字符。英语中共有五个元音,包括大写和小写: a, e, i, o, u 示例 1 输入:字符串 = "Tutorialspoint" 输出:6 解释 字符串 "Tutorialspoint" 中的元音是 u、o、i、a、o、i。总共有 6 个元

解释PHP中的晚期静态绑定(静态::)。 解释PHP中的晚期静态绑定(静态::)。 Apr 03, 2025 am 12:04 AM

静态绑定(static::)在PHP中实现晚期静态绑定(LSB),允许在静态上下文中引用调用类而非定义类。1)解析过程在运行时进行,2)在继承关系中向上查找调用类,3)可能带来性能开销。

什么是PHP魔术方法(__ -construct,__destruct,__call,__get,__ set等)并提供用例? 什么是PHP魔术方法(__ -construct,__destruct,__call,__get,__ set等)并提供用例? Apr 03, 2025 am 12:03 AM

PHP的魔法方法有哪些?PHP的魔法方法包括:1.\_\_construct,用于初始化对象;2.\_\_destruct,用于清理资源;3.\_\_call,处理不存在的方法调用;4.\_\_get,实现动态属性访问;5.\_\_set,实现动态属性设置。这些方法在特定情况下自动调用,提升代码的灵活性和效率。

See all articles