1.数组的拷贝
数组拷贝时指针的指向问题。
数组在拷贝时,指针的位置随之复制【这一点拷贝是完全一样】
但是如果拷贝的数组的指针是非法的,那么拷贝出新指针的位置进行初始化
<?php
$arr1=array('123');
end($arr1);
next($arr1);//这个指针非法
$arr2 = $arr1;//这里进行数组的拷贝
var_dump(current($arr2));//得到指向‘123’元素的指针
var_dump(current($arr1));//此时这个数组的指针有问题
?>
但是拷贝这个操作本身不能这么说:
其实质是,拷贝之后,哪个数组先执行current这个操作,哪个数组进行初始化【重点】
【值传递时,php采用一个cow【copy on write】的机制。值传递时,php其实限时进行一个引用指向,只有两个指向中第一个改变的量会指向一个新创建的值】
这是php的一个优化思路:并没有马上为新变量开辟值空间,而是先暂时引用之前的量
<?php
$arr1=array('123','234');
end($arr1);
next($arr1);//这个指针非法
$arr2 = $arr1;//这里进行数组的拷贝
var_dump(current($arr1));//得到指向‘123’元素的指针【这里就说明了这个问题】
var_dump(current($arr2));//此时这个数组的指针有问题
?>
【重点】
同理:在foreach中,出现对原数组的操作后,因为需要创建一个copy数组【使用的机制也是写时操作cow】
<?php
$arr1=array('吕布','赵云','典韦');
foreach($arr1 as $key=>$value){
var_dump($key,$value);
if($key == 2){
$arr1[] = 'hero';//这个写操作导致了foreach的copy机制
}
echo '<br>';
}
var_dump(current($arr1));//赵云【因为写操作导致foreach开启copy机制,而copy之后的写操作同样会cow原理,会导致$arr1指针停留在该位置,而foreach遍历的是$arr1的copy数组】
?>
数组指针只要超出期望值,只要对该指针进行一次查找,那么指针便指向第一个元素【指针初始化】
【重点】
foreach与指针的问题:
(1)遍历的是拷贝而不是原数组
(2)只有在原数组出现写操作之后,才会使用真正的操作。【需要结合foreach的指针移动和指针的变更来考虑数组的指针问题】
2.数组函数
结合手册进行数组研究【起码知道有这么个函数,对参数细节不需要太过深究】
3.通过函数来实现对数据结构的模拟
模拟栈和队列【对一列数据的处理:栈先进后出(相当于是弹出最后的元素)。队列先进先出(对最前面的元素的处理)】
push、pop/shift、unshift
这样便能实现列表的模拟
入栈和出栈操作之后,会对数组的元素的下标进行重新索引【而使用数组直接添加和删除元素时,下标不会重新索引】
入栈出栈节省空间,但是效率低
【函数执行的过程是一个栈的结构:就是后调用的函数要先完成,先调用的函数才能完成】【调用的函数的代码是被编译的代码区域查找已经定义的函数代码】
4.回调函数
php使用的情况就是在一个已有函数中调用那些已经定义的函数【被称作回调函数】
array_map()函数的使用【使用自己定义的函数做回调便可实现】
5.数组的排序处理
sort
按键排序和按值排序
sort():对数组的元素进行重新排序【默认升序】
ksort():对键名进行排序【默认升序】【保持键值的关系】
rsort():对数组元素进行重新排序【降序】
krsort():对键名进行排序【保持关系,降序】
asort():按照值进行排序【但是保持键值对关系】
【关于数组的排序问题,就是只有对值排序才需要考虑键值关系,而对值排序保持关系的是asort()】
natsort()自然数排序【对计算出的自然数进行排序】【效率低】
usort()自定义排序【通过使用回调实现自定义排序】
排序问题,只有需要全局进行排序的时候才会采用数据库进行排序,如果局部排序的问题,采用的还是php进行读取之后,进行排序
排序算法【重点:结合数据结构和算法进行学习】
6.实现对一个数是否是素数进行判断【素数就是除了1和本身之外没有任何数能整除该数据(有精简算法)】
<?php
function isPrime($n){
for($d=2;$d<=$n-1;$d++){
//每一个$d进行整除,这是最复杂的算法。实质上,因为这些循环的数本身有递归的关系,只需要对之前素数进行整除判断即可
if($n%$d == 0){
return false;
}
}
return true;//如果不能整除,则为素数
}
?>
//优化的算法
(1)首先该数不可能整除它的1/2【因为一个整数不可能除以大于其一般的整数(结果为1.多)】
(2)对最后整数的数量进行最后的优化【实质上,一个整数查整除的数只需要时当前数的平方根即可(如果平方根都不能整除,那么可以确定是素数)】
综上:整除算法过程中,整数的除数本身是对应的!!!
<?php
function isPrime($n) {
$sqrt = sqrt($n);
for($d=2;$d<=$sqrt;$d++){
if($n%$d==0){
return false;
}
}
return true;//如果不能整除,则为素数
}
?>
循环嵌套的问题:
【continue关键字跳到外层循环的情况】
循环嵌套中的break的使用【break内层循环】
7.筛选法【求素数的一个优化算法】
假设每个数都是素数,从前面第一个(素数)数开始筛选已知的数据范围。【进行整除筛选,一旦被整除,就将其标记为非素数】
知道筛选到sqrt值
<?php
function getPrime($n){
//首先将数据填充到数组中,做键.元素值为1【做素数标记】array_fill()
$list = array_fill(2.$n-1,1);
for($d=2,$sqrt=sqrt($n);$d<=$sqrt;$d++){
//再进行判断是否为已知素数
if($list[$d]==1) {
//进行筛选,从筛选元素的2倍开始筛选【因为小于2倍的数肯定不能整除】
for($i=$d*2;$i<=$n;$i+=$d){
//其实质是从2倍$d开始,对$d的整数倍进行查找
$list[$i]=0;//将整除倍进行置零处理
}
}
}
//将整个数组中的元素值是1的数据取出【便是素数】
foreach($list as $key=>$value){
if($value == 1){
echo $key.'<br/>';
}
}
}
?>
以上便是实现筛选!!!
寻找素数的两种算法:
(1)通过辗转相除【实现循环相除,只是控制最大除数的方法】实现找素数
(2)筛选法【最大除数已经控制,而且将最大除数内进行标记,进一步减少除数检验次数】
每个脚本运算使用的执行时间和空间的设置【这一点非常重要,需要结合自己的项目业务】
【使用空间换时间的逻辑就是这样】
另外注意isset和empty的区别:
isset判断变量是否被定义
empty相当于该值的布尔值的反义词