12.1.数组的概念和定义
数组,是指将若干数据按一定的顺序组合为一个整体。
每个数据被称为一个“单元”——数组单元。
每个单元由两部分构成:下标和值,下标也称为“键”(key),
数组的一个重要特点是:其中的数据有明确的顺序,而是,是其放入数组时的先后顺序。
数组有如下几种定义形式:
形式1:
$arr1 = array(单元1,单元2,...);
形式2:
$arr2 = [单元1,单元2,...];
单元(元素)的形式为: [下标=>]值
形式3:(不推荐)
\(arr3[下标1] = 值1;
\)arr3[下标2] = 值2;
……
数据取值的语法形式:
$数组名[下标]; //其中,下标可以是整数的,也可以是字符串的(注意有引号)
12.2.数组下标问题
12.2.1.下标的可用值
可以使用整数或字符串。
12.2.2.整数下标的特性
可以使用任意整数,也可以不显式使用下标,此时默认就是整数下标。
而且,从前往后,每一个没有使用下标的单元,系统给其分配的下标为之前所用过的整数下标的最大值+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
$arr3[] = 8; //下标为1
12.2.3.索引数组
通常是指一个数组的下标是从0开始的连续的整数。
举例1:
$arr1 = array(5, 8, 12, 2, 3);
$arr2 = [8, 22, 24, 22, 12];
$arr3[ ] = 8;
$arr3[ ] = 24;
$arr3[ ] = 22;
12.2.4.关联数组
通常是指一个数组的下标都是字符串。
$person = array(
‘name’=>’张三’,
‘age’=>18,
‘edu’=> ‘大学’,
‘salary’=>10000,
‘from’=>’北京’,
);
12.3.PHP数组的维数
按通常的数组元素的复杂程度,数组可以分为一维数组,二维数组,三维数组等等。
- 一维数组:
数组的每一个单元的值都是一个“非数组”值。
$arr1 = array(11, 12, 13, 14);
- 二维数组:
数组的每个单元的值都是一个“一维数组”。
$arr2 = array(
array(11, 12, 13),
array(21, 22, 23),
.....
);
三维数组:
数组的每个单元的值都是一个“二维数组”。
多维数组:
依此类推。。。。
不整齐数组(异形数组):
实际上,由于PHP的数组值可以是“任意数据”,因此,PHP数组的维数其实没有太大实际意义的。
所谓维数,其实是另一些编程语言中的数组的“整齐”格式的说法:一维数组类似排成一排的格子(线);二维数组类似排成一个平面的格子(面);三维数组类似堆满了一屋子的格子(体)。
而php数组,却可以更为灵活,类似这样:
array(
1, 2, array(31, 32, ), 4,
array(51, 52, 53, array(541, 542, 543, 544) ),
6, array(71, 72, 73),
);
这种数组就不好说几维的了,而可以称为“异形数组。
//求以下数组的所有项的总和:
$arr1 = [8, 12, 3, 14, 25];
$len = count($arr1);
$sum = 0;
for($i = 0; $i < $len; $i++)
{
$sum += $arr1[$i];
}
echo "<br>arr1的总和为:$sum";
//求以下数组的所有项的总和:
$arr2 = [
[8, 12, 3, 5],
[11, 2, 5, 7],
[12, 18, 3,2],
];
$arr2 = [
[1,2,3],
[4,5,6,7],
[8,9,10,11,12],
];
$len = count($arr2); //3
$sum2 = 0; //总和
$count = 0; //个数
for($i = 0; $i < $len; $i++)
{
$temp = $arr2[$i]; //这是一个数组!
$len2 = count($temp);//应该是4
for($j = 0; $j < $len2; $j++)
{
$sum2 += $temp[$j];
$count++;
}
}
echo "<br>arr2的总和为:$sum2";
echo ",平均值为:" . $sum2/$count;
12.4.数组的遍历(重点)
12.4.1.使用foreach语句遍历数组
遍历:就是对数组的每一项都“访问”到并进行所需要的数据处理。
foreach( $数组名 as [$key =>] $value){
//这里,$key和$value只是变量,它会在遍历数组的过程中,按顺序依次取得数组每个单元的下标和值。
echo “<br />{$key} >>> {$value} “;
}
foreach原理:
演示案例
//输出以下这个数组的每一项,并求其平均值:
$arr1 = array(11, 12, 13, 14);
$sum = $count = 0; //一次性给两个变量赋初值
foreach($arr1 as $value){
$sum += $value; //累加
$count++; //计数
}
echo "<br>平均值为:" . $sum / $count;
echo "<hr>";
//使用数组的遍历语法,求以下这个数组的最大值及其下标!
$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";
12.4.2.使用for循环语句遍历数组
数组的指针:每一个数组内部,都有一个“指针”,正常情况下,指针指向数组的某个单元,起初默认是指向第一个单元。
对于数组 $arr1 = array( 18, 22, 13, 28, 15, 33, );
图示如下:
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);
}
12.5.常用数组函数
max(): 获取一个数组中的最大值
min(): 获取一个数组中的最小值
count(): 获取一个数组的元素个数
in_array(): 判断一个数据是否在指定数组中。
语法形式:
$b = in_array( $数组, 数据); //结果true或false
range(): 生成某个范围的连续值的数组,比如range(3, 9)会得到数组:array(3, 4, 5, 6, 7, 8, 9, );
array_keys(): 取出一个数组中的所有“键”并放入一个索引数组中。
$arr1 = array("a", 2=>"b", "c", "x"=>"d", "e")
$v1 = array_keys($arr1); //结果是一个数组:[ 0, 2, 3, ‘x’, 4]
array_values(): 取出一个数组中的所有“值”并放入一个索引数组中。
array_push(): 将一个或多个数据放入一个数组的“末端”。
array_pop(): 将一个数组的最后一个单元删除,并返回该单元的值。
$arr1 = array("a", 2=>"b", "c", "x"=>"d", "e");
$v1 = array_pop($arr1); //结果:$v1为”e”, 并同时$arr1变为:["a", 2=>"b", "c", "x"=>"d"]
array_reverse(): 将一个数组的所有单元的顺序进行反转(最前的放最后,最后的放最前)
12.6.数组排序算法(重点/难点)
12.6.1.数组的排序问题
常用的排序函数:sort, rsort, asort, arsort
数组排序函数大全
$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]
12.6.2.冒泡排序算法
原理:
遍历一个数组,在此过程中,将相邻的两个单元的值进行比较:如果前面的比后面的大,则将两个值交换位置。这个过程到最后,数组中的最大值一定放在最后位置了。
如果将上述过程再进行一遍,则又可以确定剩余数据中的最大值放在倒数第二的位置。
然后将上述过程继续进行一遍,则可以继续确定剩余数据中的最大值放在倒数第三的位置。
依次类推。。。。。。进行若干次,就排好了。
图示:
有数组:
$arr1 = array(18, 22, 12, 15, 23, 9);
规律总结:
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;
12.6.3.选择排序算法
原理:
遍历一个数组,在此过程中,找出数组中的最大值及其位置。然后将该最大值的单元,跟数组的最后一个单元“交换位置”,这样进行一趟,数组中的最大值就一定放在最后位置了。
将上述过程中剩余的数据继续遍历一次,并做同样的事情,则此时剩余部分的最大值也能够放在剩余部分的最后位置——对整体而言就是倒数第二的位置。
依此类推。。。。。。。进行若干次,就排好了。
图示:
有数组:
$arr1 = array(18, 22, 12, 15, 23, 9);
规律总结:
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);
12.7.数组查找算法
查找算法,就是从一个数组中,找一个“目标”(可以是值,也可以是键)的算法。
数组的查找函数:
in_array() :在一个数组中找是否存在某个数据。
array_search() : 在数组中搜索给定的值,如果成功则返回相应的键名
array_key_exists() : 检查给定的键名或索引是否存在于数组中
一种查找算法:
遍历查找:不值得一提!
12.7.1.二分查找:
此查找算法针对的数组有以下条件:
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);