演算法背景:
①稀疏矩陣的類表示法:
template
<
class
t>
class
sparsematrix
sparsematrix
(int row,
int col)
:rows
(row)
,cols
(col)
,size(0
)void
multiply
(const sparsematrix
& m)
; sparsematrix
operator=(
const sparsematrix
& m);}
;
②三元組表的結構體表示法:
template
<
class
t>
struct matrixterm
};
主要演算法:行邏輯鏈結法。前提條件是三元組表按照行主索引法進行對映。同稀疏矩陣的轉置操作一樣,乘法操作也需要定義兩個輔助的陣列row_nums[i]和row_first_position[i],分別表示矩陣a第i行的非零元素數目和第i行第1個非零元素所在三元組表中對應的索引。
int
* row_nums =
newint
[rows +1]
;//各行的元素數目
int* row_first_position =
newint
[rows +1]
;//各行第乙個非零元對應的索引
對陣列row_nums的賦值如下:
for
(int i =
0; i <= rows; i++
) row_nums[i]=0
;//初始化row_nums
for(
int i =
0; i < size; i++
) row_nums[terms[i]
.row]++;
//賦值row_nums
terms[i]表示矩陣a三元組表第i號索引的元素,terms[i].row表示矩陣a這行存在元素。
對陣列row_first_position的賦值如下:
for
(int i =
0; i <= rows; i++
)//如果第i行沒有元素,則置為-1
row_first_position[i]=-
1;row_first_position[1]
=0;//第一行第乙個非零元一定在0號索引
for(
int i =
2; i <= rows; i++
)//遍歷三元組表
row_first_position[i]
= row_first_position[i -1]
+ row_nums[i -1]
;
for迴圈中從第二列開始邏輯上「遍歷」矩陣a,分析一下i = 2時,position[2]為第2列第乙個非零元應在的索引位置,它顯然等於第一行第乙個非零元所應在的索引位置 + 第一行的非零元個數,這也是邏輯上顯然成立的。對於之後的每乙個i,也顯然都有此行第乙個非零元所應在的索引位置 = 上一行第乙個非零元所應在的索引位置 + 上一行的非零元素個數。
因此,公式row_first_position[i] = row_first_position[i - 1] + row_nums[i - 1]是顯然的。
然後,初始化累加器:
t* accumulator =
new t[m.cols +1]
;//b有m.cols列,所以定義m.cols大小的累加器
for(
int i =
0; i <= m.cols; i++
) accumulator[i]=0
;//初始化累加器,分別表示各個列
就可以進入for迴圈,進入矩陣的乘法了。
在此之前,先看一下累加器的使用規則:
假設有m行k列矩陣a和k行n列的矩陣b,將二者相乘放到矩陣c中,矩陣c是m行n列的。假設有a、b矩陣如下所示:
顯然結果的c矩陣是5行5列的。根據矩陣的乘法公式,先列出計算c矩陣第一行的式子:
接著進行下一次計算時,把後面的一項分別存到累加器中:
對於矩陣a的某行的第乙個非零元素,當遍歷到它時,需要將它執行b.cols次乘法,即累加器的大小是b.cols + 1,因為不存在第0列。遍歷到a11時,需要全部掃瞄一遍b的三元組表,把那些「矩陣a的列索引 = 矩陣b的行索引」的元素與a11相乘,儲存到第b.terms[j].col號迭代器中去。然後,a11使用完畢,此時把row_first_position[i]++,表示第i行第乙個元素所在三元組表的索引+1(因為三元組表是按照行主對映的,同一行相鄰兩個非零元的索引一定相鄰)。也即,此時遍歷到a12了。對於a12,也執行相同的演算法,把那些「矩陣a的列索引 = 矩陣b的行索引」的元素與a12相乘,累加到第b.terms[j].col號迭代器中去。
顯然,執行乘法需要兩個for迴圈,外層迴圈「邏輯上」遍歷a矩陣的某一行的非零元素,內層迴圈遍歷b矩陣的三元組表,篩選那些符合條件的元素並累加到累加器中。
for
(int k =
1; k <= row_nums[i]
; k++
)//邏輯上遍歷a的第i行
row_first_position[i]++;
}
為了方便,用row_num表示當前第i行使用的元素,col_num表示當前第j列使用的元素。外層迴圈的判斷用到了row_nums陣列,第i行有x個非零元素,就執行x次外層迴圈。if語句判斷row_num還在第i行,且行元素和列元素滿足累加條件。內層迴圈完之後,把row_first_position[i]++,表示三元組表的索引加1
注意它們之間的聯絡!
完整函式**附下:
template
<
class
t>
void sparsematrix
::multiply
(const sparsematrix
& m)
else
//矩陣的第i行非空,此時要遍歷b的三元表,並在累加器中存值
row_first_position[i]++;
}//如此便得到了c矩陣第i行的各個元素的值,分別存在累加器中
for(
int k =
1; k <= m.cols; k++)}
//如此便運算完了第i行並成功存值,接下來要歸零累加器
for(
int k =
1; k <= m.cols; k++
) accumulator[k]=0
;//初始化累加器,分別表示各個列}}
*this
= result;
}
稀疏矩陣的乘法
1492.稀疏矩陣的乘法 時限 1000ms 記憶體限制 10000k 總時限 3000ms 描述計算兩個稀疏矩陣的乘法 輸入首先輸入第乙個矩陣的行數和列數,再輸入該矩陣的三元組形式,以0 0 0結束 然後輸入第二個矩陣的行數和列數,再輸入該矩陣的三元組形式,以0 0 0結束 輸出兩個矩陣相乘後得到...
資料結構 稀疏矩陣乘法演算法實現
作者zhonglihao 演算法名稀疏矩陣乘法 sparse matrix multiplication 分類資料結構 複雜度o n 2 形式與資料結構 c 一維結構體儲存 特性極簡封裝 不使用鍊錶 不需要轉置 計算過程容易理解 具體參考出處 演算法導論 寫的不想看 備註 include stdaf...
稀疏矩陣的乘法操作
此操作的演算法我就不多說了,裡面敘述得很清楚了。下面就是此程式 cpp view plain copy include include define null 0 define ok 1 define error 0 define maxsize 100 矩陣中非零元的最大值 define maxr...