数组的概念和定义

数组,是指将若干数据按一定的顺序组合为一个整体。每个数据被称为一个“单元”——数组单元。

每个单元由两部分构成:下标和值,下标也称为“键”(key),数组的一个重要特点是:其中的数据有明确的顺序,而是,是其放入数组时的先后顺序。

数组有如下几种定义形式:

//定义数组的多种形式
$a1 = [5, 1.2, true, 'abc'];
$a2 = array(5, 1.2, true, 'abc');

$a3 = ['a'=>5, 'b'=>1.2, 5=>true, 3=>'abc'];

$a4 = array(
        'host'=>'localhost',
        'db' => 'test',
        'user' => 'root',
        'pass' => '123',
    );

//也可以直接给一个数组变量的元素赋值,也构成数组:
$a5['name'] = '张三丰';//此时就已经创建了一个数组变量$a5
$a5['age'] = 18;
$a5['gender'] = '男';

//上述3行也可以这样写:
$a5 = ['name'=>'张三丰', 'age'=>18, 'gender'=>'男'];


//数组下标识别:
$a6 = array(
    'a' => 'abc',
    'def',        //0
    18,            //1
    5=>20,        //5
    'b'=>22,
    30,            //6
    );

数据取值的语法形式:$数组名[下标]; //其中,下标可以是整数的,也可以是字符串的(注意有引号)

数组下标问题

下标的可用值

可以使用整数或字符串。

整数下标的特性

可以使用任意整数,也可以不显式使用下标,此时默认就是整数下标。

而且,从前往后,每一个没有使用下标的单元,系统给其分配的下标为之前所用过的整数下标的最大值+1(对于第一个是0)。

$arr1 = array('a', 2=>'b','c','x'=>'d','e'); // 其下标分别为:0, 2, 3,‘x’, 4

$arr2 = array(5=>'a', 2=>'b', 'c', 'x'=>'d'); // 其下标分别为:5, 2, 6, ‘x’

$arr3['x'] = 5; //这一行,会自动创建一个数组,

$arr3[] = 6; //此时下标就是0

索引数组

通常是指一个数组的下标是从0开始的连续的整数。

举例1:

$arr1 = array(5, 8, 12, 2, 3);

$arr2 = [8, 22, 24, 22, 12];

$arr3 = [];
$arr3[ ] = 8;
$arr3[ ] = 24;
$arr3[ ] = 22;

var_dump($arr3); // array(3) { [0]=> int(8) [1]=> int(24) [2]=> int(22) }

关联数组

通常是指一个数组的下标都是字符串。

$dataBaseInf = array(
        'host'=>'localhost',
        'db' => 'test',
        'user' => 'root',
        'pass' => '123',
    );

PHP数组的维数

按通常的数组元素的复杂程度,数组可以分为一维数组,二维数组,三维数组等等。

一维数组:数组的每一个单元的值都是一个“非数组”值。

$arr1 = array(11, 12, 13, 14);

二维数组:数组的每个单元的值都是一个“一维数组”。

$arr2 = [
            [8, 12, 3, 5],
            [11, 2, 5, 7],
            [12, 18, 3,2],
        ];

三维数组:数组的每个单元的值都是一个“二维数组”。

多维数组:依此类推。。。。

不整齐数组(异形数组):实际上,由于PHP的数组值可以是“任意数据”,因此,PHP数组的维数其实没有太大实际意义的。

所谓维数,其实是另一些编程语言中的数组的“整齐”格式的说法:一维数组类似排成一排的格子(线);二维数组类似排成一个平面的格子(面);三维数组类似堆满了一屋子的格子(体)。

而php数组,却可以更为灵活,类似这样:

array(
    1, 2, array(31, 32, ), 4,
    array(51, 52, 53, array(541, 542, 543, 544) ),
    6, array(71, 72, 73),
    );

这种数组就不好说几维的了,而可以称为“异形数组。

数组的遍历(重点)

使用foreach语句遍历数组

遍历:就是对数组的每一项都“访问”到并进行所需要的数据处理。

foreach( $数组名 as $key => $value){
//这里,\$key和\$value只是变量,它会在遍历数组的过程中,按顺序依次取得数组每个单元的下标和值。
echo "<br/>{$key} => {$value} "";
}

演示案例1:输出以下这个数组的每一项,听求其平均值:

//输出以下这个数组的每一项,并求其平均值:
$arr1 = array(11,  12,  13,  14);
$sum = $count = 0;    //一次性给两个变量赋初值
foreach($arr1  as  $value){
    $sum += $value;        //累加
    $count++;            //计数
}
echo "<br>平均值为:" . $sum / $count;

echo "<hr>";

演示案例2:使用数组的遍历语法,求以下这个数组的最大值及其下标!

//使用数组的遍历语法,求以下这个数组的最大值及其下标!
$arr2 = array(11,  18,  21, 14, 8);

//max于存储最大值,先取出第一个值放入(假设他就是最大值)
$max = $arr2[0];    
$max_key = 0;    //就用于存储最大值的下标,对应也存入0下标
foreach($arr2 as $key => $value)
{
    if($value > $max )
    {
        $max = $value;
        $max_key = $key;
    }
}
echo "<br>最大值:$max, 对应下标:$max_key";

foreach遍历原理:

流程控制-循环结构-foreach循环
流程控制-循环结构-foreach循环

使用for循环语句遍历数组

数组的指针:每一个数组内部,都有一个“指针”,正常情况下,指针指向数组的某个单元,起初默认是指向第一个单元。

对于数组 $arr1 = array( 18, 22, 13, 28, 15, 33, );

图示如下:

下标
018
122
213
328
415
533

初始状态下,指针指向数组的第一个单元。

php中,有如下几个函数,可以针对数组指针进行相应操作:

$re = current( $arr1); //取得数组中当前指针所在单元的值;

$re = key( $arr1 ); //取得数组中当前指针所在单元的键(下标);

$re = next( $arr1 ); //将数组中的指针往后移动一个位置,并取得新位置上的值;

$re = prev( $arr1 ); //将数组中的指针往前移动一个位置,并取得新位置上的值;

$re = end( $arr1 ); //将数组中的指针移动到最后一个位置,并取得新位置上的值;

$re = reset( $arr1 ); //将数组中的指针移动到最前一个位置,并取得新位置上的值;

课堂练习:请用for(即不用foreach)来遍历如下数组,并按顺序输出其每一个单元的键和值:

$arr1 = array('a', 2=>'b', 'c', 'x'=>'d', 'e');

提示:count()函数可以求数组的长度

//请用for(即不用foreach)来遍历如下数组,
////并按顺序输出其每一个单元的键和值:
///提示:count()函数可以求数组的长度
$arr1 = array("a",  2=>"b",  "c",  "x"=>"d",  "e");    

$v1 = current($arr1);    //"a";
$k1 = key($arr1);        //0
next($arr1);            //指针往后移动一位
$v2 = current($arr1);    //'b'
$k2 = key($arr1);        //2
end($arr1);                //指针移动到最后一个单元
$v3 = current($arr1);    //'e'
$k3 = key($arr1);        //4

//先将指针移回第一个:
reset($arr1);
$len = count($arr1);
for($i = 0; $i < $len; $i++)
{
    $key = key($arr1);
    $value = current($arr1);
    echo "<br>$key :::: $value";
    next($arr1);    
}

常用数组函数

手册》函数参考》变量与类型相关扩展》数组》数组函数:https://www.php.net/manual/zh/ref.array.php

  1. max(): 获取一个数组中的最大值
  2. min(): 获取一个数组中的最小值
  3. count(): 获取一个数组的元素个数
  4. in_array(): 判断一个数据是否在指定数组中,语法形式:$b = in_array( $数组, 数据); //结果true或false
  5. range(): 生成某个范围的连续值的数组,比如range(3, 9)会得到数组:array(3, 4, 5, 6, 7, 8, 9, )
  6. array_keys(): 取出一个数组中的所有“键”并放入一个索引数组中
  7. array_values(): 取出一个数组中的所有“值”并放入一个索引数组中
  8. array_push(): 将一个或多个数据放入一个数组的“末端”
  9. array_pop(): 将一个数组的最后一个单元删除,并返回该单元的值
  10. array_reverse():将一个数组的所有单元的顺序进行反转(最前的放最后,最后的放最前)

数组排序算法(重点/难点)

数组的排序问题

常用的排序函数:sort, rsort, asort, arsort

排序函数属性:

函数名称排序依据数组索引键保持排序的顺序相关函数
array_multisort()键值关联的保持,数字类型的不保持第一个数组或者由选项指定array_walk()
asort()由低到高arsort()
arsort()由高到低asort()
krsort()由高到低ksort()
ksort()由低到高asort()
natcasesort()自然排序,大小写不敏感natsort()
natsort()自然排序natcasesort()
rsort()由高到低sort()
shuffle()随机array_rand()
sort()由低到高rsort()
uasort()由用户定义uksort()
uksort()由用户定义uasort()
usort()由用户定义uasort()
$arr1 = array("a"=>8,  "b"=>2,  "c"=>5,  "x"=>3,  "e"=>6);    
sort($arr1);        //排好了!由低到高,结果为:[2, 3, 5, 6, 8]
rsort($arr1);        //排好了!由高到低,结果为:[8, 6, 5, 2, 2]

冒泡排序算法

原理:遍历一个数组,在此过程中,将相邻的两个单元的值进行比较:如果前面的比后面的大,则将两个值交换位置。这个过程到最后,数组中的最大值一定放在最后位置了。

如果将上述过程再进行一遍,则又可以确定剩余数据中的最大值放在倒数第二的位置。

然后将上述过程继续进行一遍,则可以继续确定剩余数据中的最大值放在倒数第三的位置。

依次类推。。。。。。进行若干次,就排好了。

图示:有数组:$arr1 = array(18, 22, 12, 15, 23, 9);

原始数组第1趟之后第2趟之后第3趟之后第4趟之后第5趟之后
18181212129
22121515912
12151891515
15229181818
23922222222
92323232323

规律总结:

  1. 要进行从头到尾两两比较并进行交换位置的趟数为$n-1趟,$n是总个数(数组长度)
  2. 每次都对相邻的两个数据进行大小比较,如果需要,就交换他们的位置!
  3. 每趟要比较的次数都比前一趟少1次,第一趟要比较的次数为:$n-1

代码演示:

/*
1,要进行从头到尾两两比较并进行交换位置的趟数为$n-1趟,$n是数组长度
2,每次都对相邻的两个数据进行大小比较,如果需要,就交换他们的位置!
3,每趟要比较的次数都比前一趟少1次,第一趟要比较的次数为:$n-1
*/

$arr1 = array(18,  22,  12,   15,  23,  9);
$n = count($arr1);
//控制要进行的趟数
for($i = 0; $i < $n-1; $i++)
{
    //在每一趟里面,控制进行比较的次数
    for($k = 0; $k < $n-1 - $i;  $k++)
    {
        //如果前面一项比后面一项大,就要进行交换
        if($arr1[$k] > $arr1[$k+1] )
        {
            $temp = $arr1[$k];
            $arr1[$k] = $arr1[$k+1];
            $arr1[$k+1] = $temp;
        }
        else{
            //如果不是这样,就什么也不用做
        }
    }
}
echo "<pre>";
print_r($arr1);
echo "</pre>";

交换原理:

//普通变量的交换
$a = 3;
$b = 4;
//交换上述两个变量的值
$temp = $a;
$a = $b;
$b = $temp;
//数组单元的交换:交换其中的下标为2和下标为6的两个单元的值
$arr2 = [ 2=>15, 3=>18, 6=>20];
$temp = $arr2[2];
$arr2[2] = $arr2[6];
$arr2[6] = $temp;

选择排序算法

原理:

遍历一个数组,在此过程中,找出数组中的最大值及其位置。然后将该最大值的单元,跟数组的最后一个单元“交换位置”,这样进行一趟,数组中的最大值就一定放在最后位置了。

将上述过程中剩余的数据继续遍历一次,并做同样的事情,则此时剩余部分的最大值也能够放在剩余部分的最后位置——对整体而言就是倒数第二的位置。

依此类推。。。。。。。进行若干次,就排好了。

图示:有数组:$arr1 = array(18, 22, 12, 15, 23, 9);

原始数组第1趟之后第2趟之后第3趟之后第4趟之后第5趟之后
18181815129
222299912
121212121515
151515181818
23922222222
92323232323

规律总结:

  1. 要进行从头到尾找出其中的最大值(及下标),并进行交换的趟数为$n-1,$n为数组长度
  2. 每一趟要做的事情是:a)找最大值,吧)并将该最大值跟这一趟的最后一项进行交换;
  3. 每一趟要从中找最大值的数据个数都比前一趟少1,其中第一趟有$n个。

代码演示:

/*
规律总结:
1,要进行从头到尾找出其中的最大值(及下标),并进行交换的趟数为$n-1,$n为数组长度
2,每一趟要做的事情是:a)找最大值,吧)并将该最大值跟这一趟的最后一项进行交换;
每一趟要从中找最大值的数据个数都比前一趟少1,其中第一趟有$n个。
 */
$arr1 = array(18,  22,  12,   15,  23,  9);
//implode("字符", $数组):将该数组的所有项用给定字符“连接起来”
echo "<br>交换前:" . implode(',' , $arr1);
$n = count($arr1);
//控制进行从中找最大值的趟数:
for($i = 0; $i < $n - 1; $i++)
{
    //a)找最大值(及下标):
    //这个循环是在其中某一趟中从前(若干)个数据中找最大值
    $max = $arr1[0];    //取出这些数据中的第一项,并该变量作为最大值
    $max_key = 0;        //对应的下标
    for($k = 0; $k < $n - $i;  $k++)
    {
        if($arr1[$k] > $max)
        {
            $max = $arr1[$k];
            $max_key = $k;
        }
    }

    //b)交换:
    $temp = $arr1[$max_key];    //$max_key为这一趟找出来的最大值的下标
    $arr1[$max_key] = $arr1[$n-1-$i];    //$n-1-$i为这一趟最后一项的下标
    $arr1[$n-1-$i] = $temp;
}
echo "<br>交换后:" . implode(',' , $arr1);

数组查找算法

查找算法,就是从一个数组中,找一个“目标”(可以是值,也可以是键)的算法。

数组的查找函数:

  • in_array() :在一个数组中找是否存在某个数据。
  • array_search() : 在数组中搜索给定的值,如果成功则返回相应的键名
  • array_key_exists() : 检查给定的键名或索引是否存在于数组中

一种查找算法:遍历查找:不值得一提!

二分查找:

此查找算法针对的数组有以下条件:

  1. 索引数组;
  2. 数组是已经排好序的了。

算法演示:

//演示数组的二分查找算法:
//前提:
//1,索引数组;
//2,数组是已经排好序的了。
$arr1 = [2, 5, 8];//, 10, 15, 18, 22, 24, 24, 28,33, 35, 50, 55, 56, 57, 60, 61, 62, 66, 70];
$search = 3;    //具体分析,可以将该数据修改为不同的值,比如:2, 5, 8,
//原理:每次都找该数组的某一段的中间项,并跟要找的目标进行“对比”
//1,如果刚好相等,则就算找出来了
//2, 如果中间项比目标大,就只要去左边的那一半中找
//3, 如果中间项比目标小,就只要去右边的那一半中找

//假设有这么一个函数,它能够从某个数组$arr中的某个下标范围($start---$end)中找指定的数据$value
//这里,假设:$start一定是不能大于$end,否则,我们就认为找不到了!
function  binary_search($arr, $value, $start, $end)
{
    if($start > $end)
    {
        return false;
    }

    $mid = floor(($start + $end)/2);    //取得两个下标中的中间下标(一半位置)
    $mid_value = $arr[$mid];    //中间项的值
    //如果刚好相等,则就算找出来了
    if($mid_value == $value){
        return true;
    }
    //如果中间项比目标大,就只要去左边的那一半中找
    elseif($mid_value > $value)    //
    {
        $new_start = $start;
        $new_end = $mid-1;
        return binary_search($arr, $value, $new_start, $new_end);
    }
    //如果中间项比目标小,就只要去右边的那一半中找
    else
    {
        $new_start = $mid+1;
        $new_end = $end;
        return binary_search($arr, $value, $new_start, $new_end);
    }

}
$len = count($arr1);
$result = binary_search($arr1,$search, 0, $len-1);
var_dump($result);