1. 程式人生 > >稀疏矩陣三元組快速轉置(轉poklau123寫的很清楚)

稀疏矩陣三元組快速轉置(轉poklau123寫的很清楚)

數位 變量 為什麽 正是 spa eas 2個 如果 ast

關於稀疏矩陣的快速轉置法,首先得明白其是通過對三元表進行轉置。如果誤以為是對矩陣進行轉置,毫無疑問就算你想破腦袋也想不出個所以然,別陷入死胡同了!

對於一個三元表,行為i,列為j,值為v。需將其i與j的值對調才能得到新的三元表,但是如果直接進行轉換,得到的新的三元表的順序是混亂的,不符合三元表的規則。所以,課本首先介紹了一個用掃描來轉置的算法(這個算法比較容易,在這裏我就不說了),但是這個轉置算法的時間復雜度太高,於是就有了接下來的快速轉置算法。

要你對一個三元表進行步驟最少的轉置,你可能會想,如果知道三元表中每一項在轉置後的新的三元表中的位置,然後直接放進去,豈不是極大的縮小了時間復雜度?沒錯!快速轉置法正是基於這種思想而設計的。

技術分享圖片

那麽如何知道三元表中某一項的位置呢?在課本98頁的a.data這個三元表可以看到,j為列號,在轉置後即為新的三元表的行號,三元表正是按照行序進行排列的,而j=1有2個、j=2有2個、j=3有2個、j=4有1個、j=6有1個。根據這些數據按照從小到大排列,j=1的項在新的三元表中應占據第1、2位,j=2的項在新的三元表中應占據第3、4位,j=3的項在新的三元表中應占據第5、6位,j=4應占據第7位,j=6應占據第8位。

接下來就輕松多了,轉置的時候直接從第一項讀起,讀取其j值,比如課本中a.data這個三元表的第一項的j值為2,因為j=2占據第3、4位,所以應該從第三位開始放,接下來如果讀取的某一項的j值也是2,就放在第4位。因為j=2的項只有兩個,所以第5位絕對不會被j=2的項占據,第5、6項本來就是留給j=3的。再比如當讀到j=6的那項時,第8位是留給它的,就可以直接放進第8位了。這樣,讀取每一項,都能在三元表中找到相應的位置,這就是稀疏矩陣快速轉置的原理。

當然,上面只是快速轉置的原理,要實現它,就要設計算法來實現了。首先,我們需要兩個變量。第一個num[col]用於記錄原三元表中列數為col的項的數目,例如col=3時,num[col]=2;第二個cpot[col]用於記錄原三元表中列數為col的項在新三元表中的首位置,例如col=3時,cpot[col]=5。你可以打開書本第99頁,我想你現在應該是能看懂表5.1了吧。

技術分享圖片

接下來說一說快速轉置算法的具體事項,在課本的100頁代碼如下:

技術分享圖片

逐句解釋:

① 此函數名為FastTransposeSMatrix,形參有原三元表TSMatrix M,作用是傳入三元表;三元表TSMatrix &T,采用引用以返回一個三元表。

② 三元表T可能沒有初始化,這句的意思是將矩陣M的行數,列數,以及非零元個數傳給矩陣T,使其初始化。

③ T.tu為真時,即矩陣M中至少存在一個非零元。

④ 初始化數組num

⑤ 書中的註釋是求M中每一列含非零元的個數。具體來說,當原三元表M中某兩項或多項的j值相同時,M.data[t].j的值是相等的,因此這個循環完成後,比如說num[3]的值就是原三元表M列數為3的個數。

⑥ 書中的註釋標錯位置了,應該是第一個for循環的後面。Cpot[1]=1的用處是第一列的在新三元表T的第一個插入位置為1。Cpot[0]是留給儲存三元表行列數和非零元個數的。

⑦ 這句話是用來求除第一列外其它每一列的第一個非零元在新三元表T中的位置。第col列第一個非零元的位置為第col-1列第一個非零元的位置加上第col-1列非零元的個數,這是個非常簡單的數學問題,沒必要多說了。

⑧ M.tu的值是原三元表M的非零元個數,這個循環是用來遍歷原三元表M的每一項。

⑨ Col=M.data[p].j的作用是得到循環當前項p的列數值j,賦給col,cpot[col]的值即為第col列的第一個插入位置,如果你問為什麽,請看第七句。q=cpot[col]作用是用q來記錄當前第col列的插入位置(當然你也可以不用這個賦值,只需把接下來出現的q都改為cpot[col]就行)。

⑩ 將原三元表M的當前第p項的i,j值進行交換後給新三元表T的第q項,這樣第p項就轉置後正確的插入到新三元表的正確位置。

? 將當前原三元表的第p項的非零元的值給新三元表的第p項。後一句++cpot[col]這個自增語句是使列數位col的項在新三元表的插入位置移動一位,下次再碰到列數位col的列時,插入位置即為此次插入位置的下一個。

稀疏矩陣三元組快速轉置(轉poklau123寫的很清楚)