C 演算法 稀疏矩陣的乘法實現(行邏輯鏈結法)

2021-10-25 03:22:52 字數 4054 閱讀 9254

演算法背景:

①稀疏矩陣的類表示法:

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...