PHP数据结构(六) ——数组的相乘、广义表

PHP数据结构(六)——数组的相乘、广义表

(原创内容,转载请注明来源,谢谢)

本文接PHP数据结构(五)的内容。

4.2 行逻辑链接的顺序表

行逻辑链接的顺序表,即在上述三元表的基础上,附加一个数组,用于存储每一行第一个非零元的位置。

该存储方式,主要是便于对两个稀疏矩阵进行乘法操作。

矩阵M(a行b列)和N(b行c列)相乘(m的行必须等于n的列),结果是一个a行c列的矩阵。

根据矩阵乘法的方式,计算步骤如下:

1、矩阵M的第a’行b‘列(0<=a’<=a,0<=b’<=b)的值(非零元),只需要和矩阵N的第b‘行的每个非零元所在的列col’相乘,作为第col‘列的暂存的值。

2、遍历M的第a’行的非零元,分别进行上述操作,并把暂存的值进行相加。

3、遍历完所有M的非零元,即完成乘法操作。

现假设两个稀疏矩阵如下:

M=array(
    0=>array(0,1,25), 1=>array(1,3,15), 2=>array(2,2, 10), 3=>array(3,1,15)
);
N=array(
    0=>array(0,3,10), 1=>array(1,4,15),2=>array(2,3,20), 3=>array(3,3,30)
);

PHP计算稀疏矩阵乘法源码如下:

//稀疏矩阵乘法
//获取每一行的非零值
functiongetNotZeroRowPosi($arr){
         $arrResult = array();
         $row = 0;
         $pos = 0;
         foreach($arr as $key => $val){
                   $tmpRow = current($val);
                   if($tmpRow == $row){
                            if(!isset($arrResult[$row])){//考虑到第一次循环的时候的初始值
                                     $arrResult[$row]= $pos;                                    
                            }
                            $pos++;//计算本行占据的空间
                   }else{
                            $row = $tmpRow;
                            $arrResult[$row] =$pos++;
                   }       
         }
         return $arrResult;
}
//乘法
functionmutiArray($arr1, $arr2){
         $rowPosi2 = getNotZeroRowPosi($arr2);
         $arrResult = array();
         foreach($arr1 as $key => $val){//遍历第一个矩阵
                   $row1 = current($val);
                   $col1 = next($val);
                   $value1 = next($val);
                   for($i=$rowPosi2[$col1];;$i++){
                            if(!isset($arr2[$i])){//矩阵2取完后弹出
                                     break;
                            }
                            $tmpArr = $arr2[$i];//取出矩阵2的第i行的非零元开始数组
                            $row2 =current($tmpArr);
                            if($row2 != $col1){
                                     break;//循环结束矩阵2的第i行后,退出此循环
                            }
                            $col2 =next($tmpArr);
                            $value2 =next($tmpArr);
                            $value =$value1*$value2;
                            if(!isset($arrResult[$row1][$col2])){
                                     $arrResult[$row1][$col2]= $value;
                            }else{
                                     $arrResult[$row1][$col2]+= $value;
                            }
                   }
         }
         return $arrResult;
}
//调用乘法函数
$arrPrev =array(
         0=> array(0,1,25),1=>array(1,3,15), 2=>array(2,2, 10), 3=>array(3,1,15)
);
$arrLast =array(
         0=>array(0,3,10), 1=>array(1,4,15),2=>array(2,3,20), 3=>array(3,3,30)
);
$arrResult =mutiArray($arrPrev, $arrLast);
print_r($arrResult);
//计算结果Array ([0] => Array ( [4] => 375 ) [1] => Array ( [3] => 450 ) [2] =>Array ( [3] => 200 ) [3] => Array ( [4] => 225 ) )

4.3 十字链表

十字链表主要用于稀疏矩阵相加的情况较多时的压缩存储方式。其与链表非常相似,但是有两个next指针,一个指向本行的下一个非零元(如果没有就指向null),另一个指向本列下一个非零元(如果没有就指向null)。

另外,需要设定两个头指针数组,一个指向每一列的第一个非零元,另一个指向每一行的第一个非零元。

矩阵相加的方式:

1、当矩阵M和矩阵N相加时,如果矩阵N的第(i,j)个位置M矩阵没有值,那么就在十字链表中插入此节点。

2、将插入后的节点的next指针分别指向本行、本列的下一个节点,如果没有下一个节点指向null。

3、改变该节点的上方与左方的节点的next指针指向新插入的节点,如果没有上方或左方的节点,则由相应的头指针数组指向该节点。

4、如果矩阵N的第(i,j)个位置M矩阵有值,且M和N该值相加不等于0(因为考虑到正数加负数等同于减的情况),则只需要改变该节点的值,不需要变换指针。

5、如果矩阵N的第(i,j)个位置M矩阵有值,且M和N该值相加等于0,则需要删除此节点。操作方式为将该节点的上方的节点(包括头节点)的next指向该节点的下一个节点(没有则指向null),将该节点的左边的节点(包括头节点)的next指向该节点的右边的节点(没有则指向null)。

5、广义表

5.1 广义表表示为LS=(a1,a2,…an),其中的任意ai(1<=i<=n)可以是单个原子,如数字、字符串,也可以是广义表。即广义表是可以嵌套的。需要注意的是,’’与array()不一样,’’表示单个原子空值,array()表示没有元素的广义表。

5.2 广义表的深度即广义表中嵌套最多的层级数。

5.3 广义表通过链式结构存储,有两种存储方式。

方法一:

方法二:

5.4 根据广义表,可以做出递归算法。运用递归算法,可以算出广义表的深度。

广义表深度的计算方式,即遍历广义表的每一个ai,如果ai也是广义表,则进一步遍历ai的下一层。

广义表每一层的深度即为下一层深度的值加1,原子的深度为0,空表的深度为1。由此,可以计算广义表的深度。

PHP计算广义表的源码如下:

//计算广义表的深度
function getDeepthArr($arr){
         $curMaxDeep= 0;
         foreach($arras $item){
                   if(!is_array($item)){
                            continue;
                   }else{
                            $deep= getDeepthArr($item);
                            if($deep > $curMaxDeep){
                                     $curMaxDeep= $deep;
                            }
                   }
         }
         return$curMaxDeep+1;
}
$arr = array(array('a'), 1,array(array('a', array(array()), '')), 'a');
$deep = getDeepthArr($arr);
echo $deep;//结果为5

——written by linhxx 2017.06.23

相关阅读:

PHP数据结构(五) ——数组的压缩与转置

PHP数据结构(四) ——队列

PHP数据结构(三)——运用栈实现括号匹配

PHP数据结构(二)——链式结构线性表

PHP数据结构(一)——顺序结构线性表

原文发布于微信公众号 - 决胜机器学习(phpthinker)

原文发表时间:2017-06-23

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏和蔼的张星的图像处理专栏

53. 翻转字符串怎么说?

思路就是把单词提取出来先存入vector里,然后再从后往前一个一个取出来。 分离单词就按照空格来分离: 遍历字符串 如果不是空格,把这个字符加到一个str...

711
来自专栏小樱的经验随笔

Wannafly模拟赛 A.矩阵(二分答案+hash)

矩阵 时间限制:1秒 空间限制:131072K 题目描述 给出一个n * m的矩阵。让你从中发现一个最大的正方形。使得这样子的正方形在矩阵中出现了至少两次。输出...

2715
来自专栏bboysoul

1454: C语言实验题——三个数排序

描述:输入三个整数x,y,z,请把这三个数由小到大输出. 输入:输入数据包含3个整数x,y,z,分别用逗号隔开. 输出:输出由小到大排序后的结果,用空格隔开...

803
来自专栏CDA数据分析师

一文读懂如何用 Python 实现6种排序算法

总结了一下常见集中排序的算法 ? 归并排序 归并排序也称合并排序,是分治法的典型应用。分治思想是将每个问题分解成个个小问题,将每个小问题解决,然后合并。 具体的...

19310
来自专栏Bingo的深度学习杂货店

Q78 Subsets

Given a set of distinct integers, nums, return all possible subsets (the power s...

2798
来自专栏Brian

数据分析利器-NumPy

---- 概述 NumPy类库是Python的一种开源的数值计算扩展。这种工具可用来存储和处理大型矩阵,比Python自身的嵌套列表(nested list s...

3248
来自专栏锦小年的博客

python学习笔记2.4-数据结构之列表和元组

python语言中包含的数据结构比较简单,除了简单的变量以外,还有列表(元组)、字典、集合。对于数据结构的操作一般包含四种:增、删、查、改。本文主要介绍列表(l...

1719
来自专栏海天一树

小朋友学C语言(18):二进制

一、十进制与二进制 我们日常所用到的计数方式,是十进制(数字用0,1,2,3,4,5,6,7,8,9这十个数字来表示)。 十进制的进位规则是”逢十进一”。 比...

26510
来自专栏陈树义

如何检测链表中是存在循环

  链表在面试中出现的频率很高,有的比较正常,考链表的常规操作,主要看基本功是否扎实,有些就比较难,难在思维的改变和是否能够想到对应的点。这里出现的是其中一个题...

3195
来自专栏个人分享

二进制中1的个数

解析:如果一个整数不为0,那么这个整数至少有一位是1。如果我们把这个整数减1,那么原来处在整数最右边的1就会变为0,原来在1后面的所有的0都会变成1(如果最右边...

562

扫码关注云+社区