PHP学习笔记(一谦四益)

news/2024/11/27 0:21:07/

前言

上一篇文章 PHP学习笔记(观隅反三)分享了数组的知识,这篇文章接着分享和数组相关的算法。

算法效率

算法效率分为两种:第一种是时间效率,第二种是空间效率。时间效率被称为时间复杂度,而空间效率被称作空间复杂度时间复杂度主要衡量的是一个算法的运行速度,而空间复杂度主要衡量一个算法所需要的额外空间。

冒泡排序

冒泡排序算法的原理如下:
比较相邻的元素。如果第一个比第二个大,就交换他们两个。
对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
针对所有的元素重复以上的步骤,除了最后一个。
持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
在这里插入图片描述

$arr1=array(1,2,4,3,5,0,8);
for($j=0;$j<count($arr1);$j++){for($i=0;$i<count($arr1)-1-$j;$i++){if($arr1[$i]>$arr1[$i+1]){$temp=$arr1[$i];$arr1[$i]=$arr1[$i+1];$arr1[$i+1]=$temp;}}   
}
echo '<pre>';
print_r($arr1);
//Array ( [0] => 0 [1] => 1 [2] => 2 [3] => 3 [4] => 4 [5] => 5 [6] => 8 ) 

时间复杂度

若文件的初始状态是正序的,一趟扫描即可完成排序。所需的关键字比较次数C记录移动次数M均达到最小值:Cmin=n-1 ; Mmin=0
所以,冒泡排序最好的时间复杂度为O(n)
若初始文件是反序的,需要进行 n-1 趟排序。每趟排序要进行 n-i 次关键字的比较(1≤i≤n-1),且每次比较都必须移动记录三次来达到交换记录位置。在这种情况下,比较和移动次数均达到最大值:
在这里插入图片描述
冒泡排序的最坏时间复杂度为 O(n2)
综上,因此冒泡排序总的平均时间复杂度为 O(n2)。 [1]

稳定性

冒泡排序就是把小的元素往前调或者把大的元素往后调。比较是相邻的两个元素比较,交换也发生在这两个元素之间。所以,如果两个元素相等,是不会再交换的;如果两个相等的元素没有相邻,那么即使通过前面的两两交换把两个相邻起来,这时候也不会交换,所以相同元素的前后顺序并没有改变,所以冒泡排序是一种稳定排序算法

选择排序

选择排序原理如下:
第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。以此类推,直到全部待排序的数据元素的个数为零。选择排序是不稳定的排序方法。
在这里插入图片描述

$arr2=array(1,0,3,4,6,2,7);
for($i=0;$i<count($arr2);$i++){// 选定一个元素下标,假定其为最小元素下标,将其存储在变量$min中$min=$i;for($j=$i+1;$j<count($arr2);$j++){if($arr2[$j]<$arr2[$min]){$min=$j;}}// 如果选定的最小值不等于实际最小值,就进行交换if($min !=$i){$temp =$arr2[$i];$arr2[$i]=$arr2[$min];$arr2[$min]=$temp;}
}
print_r($arr2);
//Array ( [0] => 0 [1] => 1 [2] => 2 [3] => 3 [4] => 4 [5] => 6 [6] => 7 ) 

时间复杂度

选择排序的交换操作介于0 和 (n - 1)次之间。选择排序的比较操作为n (n - 1) / 2次之间。选择排序的赋值操作介于 0 和 3 (n - 1) 次之间。比较次数O(n^2),比较次数与关键字的初始状态无关,总的比较次数N=(n-1)+(n-2)+…+1=n*(n-1)/2。交换次数O(n),最好情况是,已经有序,交换0次; 最坏情况交换n-1次,逆序交换n/2次。 交换次数比冒泡排序少多了,由于交换所需CPU时间比比较所需的CPU时间多,n值较小时,选择排序比冒泡排序快。

稳定性

在一趟选择,如果一个元素比当前元素小,而该小的元素又出现在一个和当前元素相等的元素后面,那么交换后稳定性就被破坏了。因此选择排序是一个不稳定的排序算法。

插入排序

插入排序:
通常称之为 直接插入排序, 当进行少量数据的排序中,还可以使用插入排序的方法,插入排序的方法是将一个数据插入到已经排好序的有序数据中,以此得到一个新的个数加一的数组,该方法比较稳定
在这里插入图片描述

$arr3=array(1,0,3,4,6,2,7);
for($i=1,$len=count($arr3);$i<$len;$i++){// 选出要插入元素$temp = $arr3[$i];//选出有序数列,将待插入元素和有序数列进行比较,若前者比后者小,就将待插入元素插入到指定位置,待插入元素后的原有序数列往后移,补上待插入元素的空位for($j=$i-1;$j>=0;$j--){if($arr3[$j]>$temp){$arr3[$j+1]=$arr3[$j];$arr3[$j]=$temp;}else{// 如果当前需要插入的元素要比前面的元素大,位置正确跳出循环break;}}
}
print_r($arr3);
//Array ( [0] => 0 [1] => 1 [2] => 2 [3] => 3 [4] => 4 [5] => 6 [6] => 7 )

时间复杂度

在插入排序中,当待排序数组是有序时,此时是最优情况,即只需要和前一个数比较即可,这时比较只需要进行一次,时间复杂度是O(N)
最坏的情况是待排序数组是逆序的,此时需要比较的次数是最多的,即插入排序最坏情况的时间复杂度是 O(N2);
通常情况下,插入排序在平均情况下运行时间和最坏情况运行时间一样。

空间复杂度

插入排序的空间复杂度是常数阶 O(1)

稳定性

如果待排序的序列中存在两个或两个以上具有相同关键词的数据,排序后这些数据的相对次序保持不变,即如果排序后两个相同的数的相对顺序不会发生改变,则该算法是稳定的
如果排序后,数据的相对次序发生了变化,则该算法是不稳定的。关键词相同的数据元素将保持原有位置不变,所以该算法是稳定的

归并排序

归并排序的原理:
将数组拆成两个数组;申请一个空间用于存放合并后的数组;
假设两个数组已经排好序列,设置两个指针,指针指向的位置分别是两个已经排好序的有序数列的数组的起始位置;
两指针分别指向两个数组的起始元素,并比较两个指针所指的元素,将较小的元素放入申请的空间
然后将指针移动到下一位置;最后将另一个序列所剩的元素直接复制到合并序列中。
在这里插入图片描述

二路归并

$nums1=array(1,3,5);
$nums2=array(2,4,6);
// 申请空间用于存放合并后的数组
$nums3=array();
// 当需要合并的数组中含有元素,就进入循环
while(count($nums1) && count($nums2)){// 取出每个数组的第一个元素进行比较:array_shift() 函数删除数组中的第一个元素,并返回被删除元素的值。$nums3[]=$nums1[0]<$nums2[0]?array_shift($nums1):array_shift(($nums2));
}
// array_merge() 将一个或多个数组的单元合并起来,一个数组中的值附加在前一个数组的后面。返回作为结果的数组。
print_r(array_merge($nums3,$nums2,$nums1));//其中$nums1  $num2的顺序可颠倒
Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 [4] => 5 [5] => 6 )

归并排序

通过二路归并的例子,归并排序就更容易理解了:

$arr4=array(2,4,1,3,6,5,0);function merge($arr4){$len=count($arr4);if($len<=1) return $arr4;$mid=floor($len/2);
// array_slice() 函数返回数组中的选定部分。$left=array_slice($arr4,0,$mid);$right=array_slice($arr4,$mid);// 如果分成的两个数组没有排好序,由于是奇数个元素的数组,无法均分成两个相同元素个数的数组// 最后在进行二路合并的时候就会乱序,因此需要对$left  $right进行排序// 调用merge函数  $left=merge($left);$right=merge($right);$arr5=array();while(count($left) && count($right)){$arr5[]=$left[0]<$right[0]?array_shift($left):array_shift($right);}return array_merge($arr5,$left,$right);
}
print_r(merge($arr4));
//Array ( [0] => 0 [1] => 1 [2] => 2 [3] => 3 [4] => 4 [5] => 5 [6] => 6 ) 

时间复杂度

归并排序比较占用内存,但却是一种效率高且稳定的算法。
改进归并排序在归并时先判断前段序列的最大值后段序列最小值的关系再确定是否进行复制比较。如果前段序列的最大值小于等于后段序列最小值,则说明序列可以直接形成一段有序序列不需要再归并,反之则需要。所以在序列本身有序的情况下时间复杂度可以降至O(n)

稳定性

归并排序是稳定的排序.即相等的元素的顺序不会改变

查找算法

顺序查找

顺序查找也叫做线性查找,对于任意一个序列以及一个给定的元素,将给定元素序列中元素依次比较,直到找出与给定关键字相同的元素,或者将序列中的元素与其都比较完为止。
在这里插入图片描述

$arr2=array(4,23,54,67,3,7);
function check($arr2,$num){for($i=0;$i<count($arr2);$i++){if($arr2[$i]==$num){return $arr2[$i];}}return false;
}
var_dump(check($arr2,3));
//int(3)

二分查找算法

//二分查找$arr=array(1,4,2,3,6,5,7);//得到数组边界$right = count ($arr);$left = 0;$res = 3;//循环匹配while($left <= $right){//得到中间位置$middle = floor(($right - $left) /2);//进行查找匹配if($arr[$middle] == $res){echo $middle + 1;break;}if($arr[$middle]<$res{$left =$middle + 1;}else{$right=$middle -  1;}}

最后

以上就是这篇文章给大家带来的全部内容了,后续会持续更新相关文章,期待和大家的交流~
如有不足,感谢指正!


http://www.ppmy.cn/news/26032.html

相关文章

PostgreSQL , PostGIS , 球坐标 , 平面坐标 , 球面距离 , 平面距离

标签 PostgreSQL , PostGIS , 球坐标 , 平面坐标 , 球面距离 , 平面距离 背景 PostGIS中有两种常用的空间类型geometry和geography&#xff0c;这两种数据类型有什么差异&#xff0c;应该如何选择&#xff1f; 对于GIS来说&#xff0c;首先是坐标系&#xff0c;有两种&#…

Redis的常见操作和Session的持久化

安装Redis使用yum命令&#xff0c;直接将redis安装到linux服务器&#xff1a;yum -y install redis启动redis使用以下命令&#xff0c;以后台运行方式启动redis&#xff1a;redis -server /etc/redis.conf &操作redis使用以下命令启动redis客户端&#xff1a;redis-cli设置…

C/C++每日一练(20230218)

目录 1. 整数转罗马数字 2. 跳跃游戏 II 3. 买卖股票的最佳时机 IV 1. 整数转罗马数字 罗马数字包含以下七种字符&#xff1a; I&#xff0c; V&#xff0c; X&#xff0c; L&#xff0c;C&#xff0c;D 和 M。 字符 数值 I 1 V 5 X …

Linux 操作系统原理 — NUMA 体系结构

目录 文章目录 目录NUMA 体系结构NUMA 的基本概念查看 Host 的 NUMA TopologyBash 脚本DPDK 脚步NUMA 体系结构 NUMA(Non-Uniform Memory Access,非一致性存储器访问)的设计理念是将 CPU 和 Main Memory 进行分区自治(Local NUMA node),又可以跨区合作(Remote NUMA nod…

物联网中RocketMQ的使用

物联网中RocketMQ的使用 1. 背景 随着物联网行业的发展、智能设备数量越来越多&#xff0c;很多常见的智能设备都进入了千家万户&#xff1b;随着设备数量的增加&#xff0c;也对后台系统的性能提出新的挑战。 在日常中&#xff0c;存在一些特定的场景&#xff0c;属于高并发请…

蓝桥杯 stm32 PWM 设置占空比

本文代码使用 HAL 库。 文章目录 前言一、创建CubeMX 工程 ,占空比分析:二、相关函数:1. 获取 CNT函数2.设置CNT为 0 函数(计算器清零)3.开启TIM2_CH1的输入捕获中断函数4.TIM 回调函数三、设置上升沿,下降沿四、在lcd上显示 R40 占空比 详细代码五、设置占空比,输出 PW…

Go 数组和切片反思

切片的底层数据结构是数组&#xff0c;所以&#xff0c;切片是基于数组的上层封装&#xff0c;使用数组的场景&#xff0c;也完全可以使用切片。 类型比较 我看到 go 1.17 有对切片和数组转换的优化&#xff0c;禁不住纳闷&#xff0c;有什么场景是必须数组来完成的呢&#x…

超低成本DDoS攻击来袭,看WAF如何绝地防护

一、DDoS攻击&#xff0c;不止于网络传输层 网络世界里为人们所熟知的DDoS攻击&#xff0c;多数是通过对带宽或网络计算资源的持续、大量消耗&#xff0c;最终导致目标网络与业务的瘫痪&#xff1b;这类DDOS攻击&#xff0c; 工作在OSI模型的网络层与传输层&#xff0c;利用协…