1. 程式人生 > 其它 >PHP資料結構(五) ——陣列的壓縮與轉置

PHP資料結構(五) ——陣列的壓縮與轉置

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資料結構(一)——順序結構線性表