1. 程式人生 > 其它 >PHP資料結構(六) ——陣列的相乘、廣義表

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