首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >PHP数据结构(五) ——数组的压缩与转置

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

作者头像
用户1327360
发布2018-03-07 10:17:08
2.1K0
发布2018-03-07 10:17:08
举报
文章被收录于专栏:决胜机器学习决胜机器学习

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

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

1、数组可以看作是多个线性表组成的数据结构,二维数组可以有两种存储方式:一种是以行为主序,另一种是以列为主序。

2、当数组存在特殊情况时,为了节省存储空间,可以进行压缩存储,把相同值并有规律分布的元素只分配一个存储空间,对于零元素不进行存储。

有两种情况可以进行压缩存储——特殊矩阵与稀疏矩阵。

3、当数组为特殊的矩阵,例如数组为n阶对称矩阵(满足aij=aji)。对于该类型矩阵,可以只存储一半的数值加上对角线的内容,一共需要分配n*(n+1)/2的存储空间。同时,上(下)三角矩阵也可以用此方式进行存储。(三角矩阵为一半有值,另一半值为0的矩阵)

存储N阶对称矩阵的方式,即以对称对角线为分界,仅取其中一半的内容以及对角线进行存储。

PHP压缩与还原n阶对称矩阵的源码如下:

         <?php
//存储n阶对称矩阵
function symmetricMatrixSave($n,$arr){
         $arrResult= array();
         $k= 0;//结果数组的下标
         for($i=0;$i<$n;$i++){
                   for($j=0;$j<=$i; $j++){
                            $arrResult[$k++]= $arr[$i][$j];
                   }
         }
         return$arrResult;
}
//还原n阶对称矩阵
function symmetricMatrixRe($arr){
         $rank= $arr[0];
         $arrResult= array();
         $row= 0;
         $col= 0;
         for($k=0;$k<count($arr); $k++){
                   //根据取出的值还原半边
                   $arrResult[$row][$col]= $arr[$k];
                   //根据对称性还原另一半
                   $arrResult[$col][$row]= $arrResult[$row][$col];
                   $col++;
                   //根据存储规则,只存一半的值,因此col不会大于row
                   if($col> $row){
                            $col= 0;
                            $row++;
                   }                
         }
         return$arrResult;
}
//调用n阶矩阵的存储还原
$arr = array(
         0=> array(0, 1, 2, 3),
         1=> array(1, 2, 3, 4),
         2=> array(2, 3, 4, 5),
         3=> array(3, 4, 5, 6)
);
print_r($arr);
//打印原数组Array ( [0]=> Array ( [0] => 0 [1] => 1 [2] => 2 [3] => 3 ) [1] => Array( [0] => 1 [1] => 2 [2] => 3 [3] => 4 ) [2] => Array ( [0] =>2 [1] => 3 [2] => 4 [3] => 5 ) [3] => Array ( [0] => 3 [1] =>4 [2] => 5 [3] => 6 ) )

echo '<br />';
$arrResult = symmetricMatrixSave(4, $arr);
print_r($arrResult);
//压缩后的结果Array ( [0]=> 0 [1] => 1 [2] => 2 [3] => 2 [4] => 3 [5] => 4 [6] => 3[7] => 4 [8] => 5 [9] => 6 )
echo '<br />';
$arrRe = symmetricMatrixRe($arrResult);
print_r($arrRe);
//还原后的结果,与压缩前相同Array ([0] => Array ( [0] => 0 [1] => 1 [2] => 2 [3] => 3 ) [1] =>Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 ) [2] => Array ( [0]=> 2 [1] => 3 [2] => 4 [3] => 5 ) [3] => Array ( [0] => 3 [1]=> 4 [2] => 5 [3] => 6 ) )

4、当矩阵为稀疏矩阵,即在m*n的矩阵中,有t个不为0的元素,且满足t/(m*n)<=0.5。稀疏矩阵通常用三元数组进行存储,(i,j,value)分别表示不为零的元素的行、列以及值。

除了上述的三元数组的压缩方式,稀疏矩阵还有两种压缩方式。分别是行逻辑链接的顺序表、十字链表。

4.1 三元组顺序表

三元组顺序表以行为主序,以列为次序,从小到大进行排列。例如:[(0,1,30),(0,3,50),(1,2,18),(3,5,20)],表示该稀疏矩阵共有四个非零元素,分别在(0,1)、(0,3)、(1,2)、(3,5)四个位置,值分别是30、50、18、20。

该方法存储的表,要进行转置操作非常便利。转置需要进行三步操作,分别是:行列的值进行转换、i和j进行转换、重新从小到大排列i和j。因此,转置的重点在于最后一步——排序。

对于排序,可以通过从0开始扫描原数组的列,并将结果相应放入新数组的行。也可以采用下述的快速转置法。

快速转置数组算法:

假设原矩阵为M,新矩阵为T,引入两个新的数组,数组num[col]为第col列非零元的个数,cpot[col]为第col列第一个非零元在新矩阵T生成的三元组顺序表的位置。在转置前,先通过原矩阵M获取这两个数组,用于快速转换的计算。

PHP快速转置稀疏矩阵的源码如下:

<?php
//快速转置稀疏矩阵
//根据原标准三元数组获取每一列非零元个数及第一个非零元的位置
/* 输入要求
array(
         0=>array(0,1,33),
         1=>array(0,5,67),
         2=>array(1,2,66),
         3=>array(3,4,55)
)*/
function getAuxiliaryArray($arr){
         $num= array();//每一列非零元个数
         foreach($arras $key => $val){
                   $num[next($val)]++;//next($val)获取列值
         }
         ksort($num);//根据键对数组升序排列
         $row_position= 0;
         $cpot= array();
         foreach($numas $key => $val){
                   $cpot[$key]= $row_position;
                   $row_position= $row_position + $val;
         }
         returnarray('num'=>$num, 'cpot'=>$cpot);
}
//转置方法
function getReverse($arr, $num, $cpot){
         $arrResult= array();
         foreach($arras $key => $val){
                   $row= current($val);
                   $col= next($val);
                   $val= next($val);
                   $arrResult[$cpot[$col]]= array($col, $row, $val);
                   $cpot[$col]++;//用于存放同一列下一个值的位置
         }
         return$arrResult;
}
$arrPrev = array(
         0=>array(0,1,33),
         1=>array(0,5,67),
         2=>array(1,2,66),
         3=>array(2,2,69),
         4=>array(3,4,55)
);
$arrTemp = getAuxiliaryArray($arrPrev);
$arrAfter = getReverse($arrPrev,$arrTemp['num'], $arrTemp['cpot']);
print_r($arrAfter);
//输出Array ( [0] =>Array ( [0] => 1 [1] => 0 [2] => 33 ) [1] => Array ( [0] => 2[1] => 1 [2] => 66 ) [2] => Array ( [0] => 2 [1] => 2 [2] =>69 ) [3] => Array ( [0] => 4 [1] => 3 [2] => 55 ) [4] => Array ([0] => 5 [1] => 0 [2] => 67 ))

——written by linhxx 2017.06.23

相关阅读:

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

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

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

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

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-06-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 决胜机器学习 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档