数组

数组基础

PHP中,数组的下标可以是整数或字符串。(注意:数组的元素不是由下标决定,而是由其“加入”的顺序决定

定义形式:

array(1, 5, 1.1, "abc", true, false);    //可以存储任何数据,此时“默认下标”
array(2=>1, 5=>5, 3=>1.1, 7=>"abc", 0=>true);//下标可以任意设定,无需顺序,无需连续
array(2=>1, 5, 1=>1.1, "abc", 0=>ture)    //可以加下标,可以使用默认下标
              //默认下标规则:前面使用过的最大数字下标加1,该数组下标为:2,3,1,4,0
array(2=>1, "dd"=>5, 1=>1.1, "abc", 0=>true);//混合下标同样遵循默认下标规则
array(-2=>1, "dd"=>5, 1.1, "abc", true);//负数小标当做字符串,则最后三项下标为0,1,2
array(2.7=>1, "dd"=>5, 1=>1.1, "abc", 0=>true);//浮点数下标会自动转换为整数且去掉小数
array("2.7"=>1, "dd"=>5, "11"=>1.1, "abc", true);//纯数字字符串下标当做数字看待
                                            //则此时下标为:2,“dd”,11,12,13
array(2=>1, "dd"=>5, true=>1.1, "abc", false=>true);//布尔值为下标,则true为1,false为0
array(2=>1, "dd"=>5, 2=>1.1, "abc", true);  //如果下标跟前面的重复,
                                            //则只是单纯覆盖前面同名下标的值
                                            //此时相当于Array(2=>1.1, “dd”=>5, ”abc”, true);

        其他形式:

$arr1[] = 1;
$arr1[] = 5;
$arr1[] = 1.1;    //直接在变量后面使用[],其转化为数组并依次赋值
$arr1['aa'] = 1;
$arr1[5] = 1.1;    //此种语法符合array()语法结构

取值:

  1. 通过下标直接取值
  2. 通过指针操作函数直接取得对应数据

赋值:赋值即定义

 

数组的分类

从键值关系:

  • 关联数组:通常指下标为字符串并且该字符串大体能表达出数据的意义的数组
$person = array(
            "name"=>"小明",
            "age"=>18
            );
  • 索引数组:通常指下标严格由0连续排列的数组,js中的数组只能这样。

 

从数组的层次来分

一维数组:数组中的每一个元素都为普通值(非数组)

二维数组:数组中的每个元素都为一个一维数组,如:

$arr1 = (array(1, 2, 3), array(1, 3), array(1));

多维数组:数组中的每个元素都为若干个数组嵌套而成的数组,取值为:$v1 = 数组名[下标1][下标2][......]

 

数组函数

在PHP中,有许多函数都为数组而生,它们能完成各种各样的功能且算法效率比较高

  • 指针操作函数:current、key、next、prev、reset、end、each
  • 单元操作函数:array_pop、array_push、array_shift、array_unshift、array_slice、array_splice
  • 排序函数:sort、asort、ksort、usort、rsort、arsort、krsort、shuffle
  • 查找函数:in_array、array_key_exists、array_search
  • 其他函数:count、array_reverse、array_merge、array_sum、array_key、array_values、array_map、array_walk、range

 

数组遍历

遍历基本语法

foreach($arr as [$key =>]$value){    //括号中部分可省略
    //进行对$key和$value的操作,$key为每次取得的元素下标,可能是数字或字符串
    //$value:每次取得的元素
    //此循环结构从第一项一直遍历到最后一项
}

 

数组指针和遍历原理

数组内部有一个指针,该指针决定数组当前取值的时候取到的元素,foreach遍历过程中,指针从第一项依次往后直到最后一项

指针除了赋值foreach循环的位置设定外,还有一些函数也依赖于指针

  1. $v1 = current($arr1);    //取得$arr1中当前指针指向的元素,如果没有指向元素返回false
  2. $v1 = key($arr1);    //取得$arr1中当前指针所指向的元素下标,没有指向元素则返回false
  3. $v1 = next($arr1);    //将指针移向”下一个元素“,然后取得该下一个元素的值
  4. $v1 = prev($arr1);    //将指针移向“上一个元素”,取得上一个元素的值
  5. $v1 = reset($arr1);    //将指针移向“第一个元素”,然后取得该元素的值
  6. $v1 = end($arr1);    //将指针移向“最后一个元素”并取得该元素的值
  7. $v1 = each($arr1);    //取得当前元素的下标和值并移动指针到下一个位置 

数组遍历的流程图:

数组

for+next+reset遍历数组

reset($arr1);        //重置数组:即数组初始化,返回的数据丢弃
$len = count($arr1);
for($i = 0; $i<$len; ++$i){
    $key = key($arr1);
    $value = current($arr1);
    //对下标和值的操作
    next($arr1);    //移动指针到下一个元素
}

求奇数偶数的和简单

 

while+each()+list()遍历数组

each()函数解释:

each()函数可取得一个数组中的元素下标和值并放入一个新的数组中,指针后移一位。此新的数组中含有4个元素,存储的数下标和值的双份:形式:array(1=>取出来的值,’value’=>取出来的值,0=>取出来的下标,’key’=>取出来的下标);

数组

list()语言结构(不是函数)解释:

使用形式:list($v1, $v2, $v3, $v4, ...) = 数组arr1;

作用:依次取得数组$arr1中下标为0,1,2,3,...的元素并一次性放入多个元素中。$v1 = $arr1[0]; $v2 = $arr1[1]; ....

注意:只能实现这样的“从0开始”的连续数字的取值(并非要求数组元素的下标顺序为0,1,2,3,...)

数组

使用这2个函数和while循环结构来实现数组遍历:

reset($arr1);
while(list($key, $value) = each(arr1)){    //从数组中一次次取得元素并赋给相应变量
    //操作
}

 

foreach遍历细节探讨

foreach为正常的循环语法结构,可以有break和continue等操作。

遍历过程值变量可认为设定为引用传递(默认为值传递)

  • foreach($arr as $key => &$value){}
  • 键变量不可设定为引用传递

数组

foreach默认是在原数组上进行遍历,如果在遍历过程中对数组进行了某种修改或指针性操作,则会复制原数组在原来的数组上进行操作

数组

foreach中如果值变量为引用传递,则无论怎样都在原数组上进行

 

数组排序思想介绍

冒泡排序

目标:将数组进行正序或逆序排列。

$arr2 = array(5, 15, 6, 8, 4);

排序过程描述:

1,对该数组从第一个元素开始,从左到右,相邻的2个元素比较大小:如果左边的比右边大,则将它们交换位置:
    array(5, 15, 6, 8, 4);    //初始5个元素进行4次循环
    array(5, 6, 15, 8, 4);    //5与16进行比较并安排顺序
    array(5, 6, 8, 15, 4);
    array(5, 6, 8, 4, 15);
    此时进入第二趟循环:
    array(5, 6, 8, 4, 15);    //此时最右边的值已为最大值,相当于为左边4个数进行排序,3次循环即可
    array(5, 6, 8, 4, 15);    //依次类推
    array(5, 6, 4, 8, 15);
    此时进入第三趟循环:
    array(5, 6, 4, 8, 15);
    array(5, 4, 6, 8, 15);
    此时进入第四趟循环:
    array(4, 5, 6, 8, 15);
    

逻辑描述:(假设数组有n项)

  1. 需要进行n-1趟的“冒泡”排序过程
  2. 每一趟的比较都比以前少1趟,第一趟为n-1次
  3. 每次比较都是从数组的开头跟相邻的元素比较并选择是否交换

 

选择排序

目标:将下列数组进行正序排列。

$arr2 = array(5, 15, 6, 8, 4);

一般性描述:

  1. 取得该数组中的最大值及其下标并跟数组的最后一项“交换”
  2. 取得该数组中除最后一项的最大值及其下标并跟倒数第二项交换
  3. 取得该数组中除最后两项的最大值及其下标并跟倒数第三项交换
  4. 取得该数组中除最后三项的最大值及其下标并跟倒数第四项交换
最初 5 15 6 8 4
第1趟 5 4 6 8 15
第2趟 5 4 6 8 15
第3趟 5 4 6 8 15
第4趟 4 5 6 8 15

    逻辑描述:(假设数组有n项)

  1. 进行n-1趟才能得出结果
  2. 每一趟找的数据都比前一趟少一个,第一趟要找n个
  3. 每次找出最大值所在的项,每次进行交换的位置依次减1,第一次的位置为n-1

 

数组查找

从数组找相应的数据(数据或下标),所研究的问题无非2个

  1. 判断数据是否存在
  2. 找出相应数据的位置(下标)

 

顺序查找

按照顺序找出相应信息

1,判断数据是否存在

$v1 = 10;
function search($arr, $v1){
    foreach($arr as $value){
        if($v1 == $value)
            return true;
    }
    return false;
}

2,找出数据的位置

$v1 = 10;
function search($arr, $v1){
    foreach($arr as $value){
        if($v1 == $value)
            return $key;
    }

    return false;
}
//注意一下调用该函数的用法
if($m = search($arr, 10) === false)    //这里用全等因为以0位下标返回的值会导致错误
    echo "没找到";
else
{

}

 

二分查找:

前提:数组已经排序OK,下标索引连续。

思路如下:对于一个很长的数组,在查找数据时,可先将数组的中位值与其比较,(假设该数组为正序排列的数组)当该中位值大于查找的数据时,说明如果该查找数据存在的话只可能存在在数组的前半部分,这样可把前面一半的数据看成一个独立的数组,这样查找数据的范围就减少了一半,依次类推.......,查找到最后时,若该数组中有与其相等的值直接退出返回其下标,否则到最后查找的数组的最后的下标会小于首下标则退出,返回该数据不存在该数组中(建议用递归解决该问题)

递归函数逻辑模型如下:

function search(数组名, 要查找的数据, 数组的头下标, 数组的尾下标){
        if(数组的头下标 > 数组的尾下标)        
            return 查找不到数据;
        //1,取中位值的下标(利用头下标和尾下标)
        //2,比较中位值和查找的数据
        if(中位值 == 查找的数据)        
            return 对应的下标
        else if(中位值 > 查找的数据){
            //将头下标和尾下标改变
            return function search(数组名, 要查找的数据, 数组的头下标, 数组的尾下标); 
        }
        else
        {
            //将头下标和尾下标改变
            return function search(数组名, 要查找的数据, 数组的头下标, 数组的尾下标); 

        }
    
}