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 条评论
登录 后参与评论

相关文章

来自专栏老九学堂

常用排序算法总结

一种是比较排序,时间复杂度O(nlogn) ~ O(n^2),主要有:冒泡排序,选择排序,插入排序,归并排序,堆排序,快速排序等。

973
来自专栏韦弦的微信小程序

Swift 两数之和 - LeetCode

482
来自专栏desperate633

LintCode 数字组合题目分析代码

给出一组候选数字(C)和目标数字(T),找到C中所有的组合,使找出的数字和为T。C中的数字可以无限制重复被选取。

371
来自专栏mukekeheart的iOS之旅

海量数据处理利器之布隆过滤器

      看见了海量数据去重,找到停留时间最长的IP等问题,有博友提到了Bloom Filter,我就查了查,不过首先想到的是大叔,下面就先看看大叔的风采。 ...

3105
来自专栏程序员叨叨叨

6.1 关系操作符(Comparison Operators)

在上一章中,我们已经介绍了Cg语言的基础数据类型(7种)、内置数据类型,以及数组、结构、接口等类型,本章将在此基础上讨论Cg中的表达式,表达式由操作符(oper...

392
来自专栏锦小年的博客

Python数据分析(2)-pandas数据结构操作

pandas是一个提供快速、灵活、表达力强的数据结构的Python库,适合处理‘有关系’或者‘有标签’的数据。在利用Python做数据分析的时候,pandas是...

21410
来自专栏Android Note

Kotlin —  Sealed Classes(密封类)

833
来自专栏灯塔大数据

每周学点大数据 | No.13 Misra Gries算法

No.13期 Misra Gries算法 Mr. 王:嗯,所以我们提出如下的方法: (1)处理一个新到来的元素x时 (2)If已经为其分配计数器,增加之 (3...

3256
来自专栏蜉蝣禅修之道

Apriori算法的Python实现

1454
来自专栏xcywt

《大话数据结构》一些基础知识

第一章 数据结构绪论 1.4 基本概念和术语 1.4.1 数据 数据:描述客观事物的符号,是计算机中可以操作的对象,是能被极端及识别,并输入给计算机处理的符号集...

3329

扫描关注云+社区