日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

5.3矩阵乘积(三元组存储结构)

發布時間:2025/3/15 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 5.3矩阵乘积(三元组存储结构) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

行邏輯鏈表的順序表

為了便于隨機存取任意一行的非零元,則需要知道每一行的第一個非零元在三元組表中的位置。為此,可將上節快速轉置矩陣中的算法創建的,指示“行”信息的輔助數組cpot固定在稀疏矩陣的存儲結構中。稱這種"帶行鏈接信息"的三元組表為行邏輯鏈接的順序表。

描述如下:

typedef struct{Triple data[MAXSIZE + 1]; //非零元三元組表int rpos[MAXRC + 1]; //各行第一個非零元的位置表int mu, nu, tu; //矩陣的行數、列數和非零元個數 }RLSMatrix;
P·S

這里的MAXSIZE在上一節有交代。這個data[MAXSIZE+1]為什么要加一呢,因為data[0]未用,同樣rpos[MAXRC+1]也是這個道理。


我們現在來看在數學里面,兩個矩陣做乘積運算應該怎么算。

如下圖所示:


P·S:本人字丑,大家將就看吧。

另外大家要知道矩陣相乘的條件:矩陣只有當左邊矩陣的列數等于右邊矩陣的行數時,它們才可以相乘,乘積矩陣的行數等于左邊矩陣的行數,乘積矩陣的列數等于右邊矩陣的列數。


這樣我們就知道,當一個不用三元組表示的矩陣M(m1行n1列)和一個矩陣n(m2行n2列)相乘時,有一個經典算法,就和上面那數學運算一模一樣。

代碼如下:

for (i = 1; i <= m1; i++) {for (j = 1; j <= n2; j++){Q[i][j] = 0;for (k = 1; k <= n1; k++){Q[i][j] += M[i][k] * N[K][j];}} }
分析下:

因為產生的矩陣是m1行n2列的矩陣,所以第一個for里面限定條件是m1,第二個for限定條件是n2,第三個for就是把第一個矩陣里面的行和第二個矩陣的列相乘并且加起來。這個Q[i][j]的作用就是先把存儲到那一塊的內存初始化,免得有其他數據影響。


下面,我們的問題來了,當用三元組存儲結構時呢?用三元組時我們一般是稀疏矩陣。

也就是說當M和N是稀疏矩陣并用三元組表作存儲結構時,不能用上面那個算法。


如下面這個例子:


那么,他們的三元組M.data、N.data和Q.data分別為:



在此補充下rpos

矩陣N的rpos值(代碼中會用到)

row1234
rpos[row]1235

矩陣M的rpos值

row123
rpos[row]134

rpos[row]指:第row行中第一個非零元在N.data中的序號。不難理解。大家對照上面的表就能填出來。





下面給出書中的偽代碼:

2017年版的嚴蔚敏版數據結構

Status MultSMatrix(RLSMatrix M, RLSMatrix N, RLSMatrix &Q) {// 求矩陣乘積Q=M*N,采用行邏輯鏈接存儲表示。int arow, brow, p, q, t, ctemp[30], l, ccol, tp;if (M.nu != N.mu) return ERROR;Q.mu = M.mu; Q.nu = N.nu; Q.tu = 0; // Q初始化if (M.tu*N.tu != 0) { // Q是非零矩陣for (arow = 1; arow <= M.mu; ++arow) { // 處理M的每一行for (l = 1; l <= M.nu; ++l) ctemp[l] = 0; // 當前行各元素累加器清零Q.rpos[arow] = Q.tu + 1;if (arow < M.mu) tp = M.rpos[arow + 1];else tp = M.tu + 1;for (p = M.rpos[arow]; p < tp; ++p) { // 對當前行中每一個非零元 brow = M.data[p].j; // 找到對應元在N中的行號if (brow < N.mu) t = N.rpos[brow + 1];else t = N.tu + 1;for (q = N.rpos[brow]; q< t; ++q) {ccol = N.data[q].j; // 乘積元素在Q中列號ctemp[ccol] += M.data[p].e * N.data[q].e;} // for q} // 求得Q中第crow( =arow)行的非零元for (ccol = 1; ccol <= Q.nu; ++ccol) // 壓縮存儲該行非零元if (ctemp[ccol]) {if (++Q.tu > MAXSIZE) return ERROR;Q.data[Q.tu].i = arow;Q.data[Q.tu].j = ccol;Q.data[Q.tu].e = ctemp[ccol];} // if} // for arow} // if return OK; } // MultSMatrix

分析下:

這里,我們要有一個思路:在經典算法里面,無論M(i,k)和N(k,j)的值是否為0,都要進行一次乘法運算,而實際上,這兩者有一個值不為0時,其乘積也是0.所以,在稀疏矩陣進行運算時,要避免這種無效果操作,只需要在M.data和N.data中找到相應的各對元素(即M.data中的j值和N.data中的i值相等的各元素)乘積即可。


此函數一開始的M.nu!=N.mu就返回ERROR,這就是我剛剛說的矩陣要相乘應該滿足的條件。


在if語句M.tu*N.tu!=0,這是為了判斷他是不是非0矩陣,如果是非0矩陣,就直接返回。


在這個for(l=1;l<=M.nu;++l)里面這個是把nu是列。這時可能有人會問,為什么nu是列,而注釋里面是把當前行各元素累加器清0,原因是他把當前行的元素清0,當前行到底有多少個元素,只能靠列來算。


隨后的Q.rpos[arow]=Q.tu+1;這里有網友可能會問兩個問題,一個是這個這個Q.rpos[arow]有什么用把后面那個賦值給他有什么含義,第二個就是為什么要Q.tu+1(為什么要總元素+1)。Q.rpos[arow]這個東西就是Q中各行第一個非零元的位置表。Q.tu+1是因為第一個就是1,這里面不可能從0開始。


下面這個if(aow<M.mu)else這個,這個tp是得到了下一行的第一個元素的位置。所以拿他當下面那個for循環的限制條件。


剩下的代碼和上面的有很多相似之處,在此不再說明了。




總結

以上是生活随笔為你收集整理的5.3矩阵乘积(三元组存储结构)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。