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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

5.3矩阵的压缩存储(稀疏矩阵转置和快速转置)

發布時間:2025/3/15 编程问答 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 5.3矩阵的压缩存储(稀疏矩阵转置和快速转置) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在矩陣中有許多值相同的元素或者是零元素。有時為了節省存儲空間,可以對這類矩陣進行壓縮存儲。所謂的壓縮存儲是指:為多個值相同的元值分配一個存儲空間;對零元不分配空間。


5.32稀疏矩陣

在m*n的矩陣中,有t個元素不為零。零α=t/m*n,稱 α為矩陣的稀疏因子。通常認為α<=0.05時稱為稀疏矩陣。


對于稀疏矩陣的非零元我們有下面這個表示:

如:(,(1,2,12),(1,3,9),(3,1,-3),(3,6,14),(4,3,24),(5,2,18),(6,1,15),(6,4,-7))

如下圖所示:




下面我們來看下三元組的結構體:

下面是書中代碼(嚴蔚敏版的數據結構)

#define MAXSIZE 12500 //非零元素個數的最大值為12500 typedef struct{int i, j; //該非零元的行下標和列下標ElemType e; }Triple;typedef struct{Triple data[MAXSIZE + 1]; //非零元三元組表,data[0]未用int mu, nu, tu; //矩陣的行數、列數和非零元個數 }TSMatrix; 分析下:

這里的思路和我們在鏈表上看到的有相似之處,結點變成了非零元素,線性表編程了非零元三元組的表。但多出了矩陣的行數,列數和非零元個數




學過線性代數的都知道,轉置運算是一種最簡單的矩陣運算。

對應一個m*n的矩陣M它的轉置矩陣是T,如下圖所示:


P·S:所謂的置換就是行和列進行交換,也就是關于主對角線對稱(矩陣左上角到右下角的線稱為主對角線)


而在程序里面,他將會是下面這張圖這樣:


這里的i對應行,j對應列,v表示值。


從分析a和b之間的差異可見只要做到:

1.將矩陣的行列值相互轉換。

2.將每個三元組中的i和j交換。

3.重排三元組之間的次序便可實現矩陣的轉置。


下面是書中給我們提供的偽代碼:

Status TransposeSMatrix(TSMatrix M, TSMatrix &T) { // 采用三元組順序表存儲表示,求稀疏矩陣M的轉置矩陣Tint p, q, col;T.mu = M.nu; T.nu = M.mu; T.tu = M.tu;if (T.tu) {q = 1;for (col = 1; col <= M.nu; ++col)for (p = 1; p <= M.tu; ++p)if (M.data[p].j == col){T.data[q].i = M.data[p].j; T.data[q].j = M.data[p].i;T.data[q].e = M.data[p].e; ++q;}}return Ok; } // TransposeSMatrix 下面來分析下:

col表示列,從M矩陣的第一列開始。比如col=1時,他先檢索M的第一列,把非零元中第一列的換成T中的第一行,就這個思路。




下面是矩陣的快速轉置方法:

原理是:如果能預先確定矩陣M中每一列(即T中每一行)的第一個非零元在b.data中(上面那圖是b.data)恰當位置。那么在對a.data中的三元組一次做轉置時,便可直接放到b.data中恰當的位置上去。

設兩個向量:num和cpot

num[col]表示矩陣M中第col列中的非零元素個數。

cpot[col]指M中第col列的第一個非零元在b.data中的恰當位置。

有下面兩個公式:

cpot[1]=1;

cpot[col]=copt[col-1]+num[col-1] 2<=col<=a.nu


圖如下:


下面來分析下這個表:

cpot[1]=1.

cpot[2]=num[1]+cpot[1]=1+2=3

cpot[3]=num[2]+cpot[2]=2+3=5

cpot[4]=num[3]+cpot[3]=2+5=7

cpot[5]=num[4]+cpot[4]=1+7=8

cpot[6]=num[5]+cpot[5]=0+8=8

cpot[7]=num[6]+cpot[6]=1+8=9

這個表就是這么填的,但是在代碼里面就不一樣了。我這里先提一下,代碼里面有覆蓋和范圍這種概念,這是什么意思,意思就是,大家看cpot[5]和cpot[6]都是8,那么在最后,他只會保留cpot[6],而cpot[7]他這里是9,但本身就只有8個元素,哪來第九個呢?所以這個cpot[9]在程序里面是沒有用的。


下面是書中代碼:

Status FastTransposeSMatrix(TSMatrix M, TSMatrix &T) { // 采用三元組順序表存儲表示,求稀疏矩陣M的轉置矩陣Tint col, t, p, q;int num[20], cpot[20];T.mu = M.nu; T.nu = M.mu; T.tu = M.tu;if (T.tu) {for (col = 1; col <= M.nu; ++col) //對列數進行初始化num[col] = 0;for (t = 1; t <= M.tu; ++t) // 求 M 中每一列所含非零元的個數++num[M.data[t].j];cpot[1] = 1;// 求 M 中每一列的第一個非零元在 b.data 中的序號for (col = 2; col <= M.nu; ++col) cpot[col] = cpot[col - 1] + num[col - 1];for (p = 1; p <= M.tu; ++p) {col = M.data[p].j; q = cpot[col];T.data[q].i = M.data[p].j; T.data[q].j = M.data[p].i;T.data[q].e = M.data[p].e; ++cpot[col];} // for} // ifreturn OK; } // FastTransposeSMatrix 分析如下:

這個程序的關鍵就是他只用了一個for循環,而上面那個程序用了兩個for循環,這使得時間復雜度降低了。這個for(p=1;p<M.tu;++p).這個就是我剛剛在上表說的那個意思。這里有個++cpot[col]這是個關鍵

現在來解釋下++cpot[col]:

我們可以看到上表中cpot[col]只有1,3,5,7,8而2,4,5沒有,所以用了這個++cpot[col]后他就把每一列的第一個元素移到了第二個。




如果還有同學不懂,下面我給出全部的代碼。

不懂的同學單步調試下。

#include <stdio.h> #include <windows.h> #define MAXSIZE 1250 #define OK 1 #define ERROR 0 #define TRUE 1 #define FLASE 0 typedef int Status; typedef int ElemType;typedef struct{int i, j; //該非零元的行下標和列下標 ElemType e; //非零元對應的值 }Triple;typedef struct{Triple data[MAXSIZE + 1]; //非零元三元組表,data[0]未用 int mu, nu, tu; //矩陣的行數,列數,非零元個數 }TSMatrix;Status FastTransposeSMatrix(TSMatrix M, TSMatrix &T) //快速轉置 { //采用三元組順序表存儲表示,求稀疏矩陣M的轉置矩陣T T.mu = M.nu;T.nu = M.mu;T.tu = M.tu;if (T.tu){int col;int num[100], cpot[100];for (col = 1; col <= M.nu; ++col)num[col] = 0; //num數組的初始化 for (int t = 1; t <= M.tu; ++t)++num[M.data[t].j]; //求M中每一列含有的非零元個數 cpot[1] = 1;for (col = 2; col <= M.nu; ++col)cpot[col] = cpot[col - 1] + num[col - 1]; //求cpot向量 int q;for (int p = 1; p <= M.tu; ++p){col = M.data[p].j;q = cpot[col];T.data[q].i = M.data[p].j;T.data[q].j = M.data[p].i;T.data[q].e = M.data[p].e;++cpot[col];}//for }//if return OK; }//FastTransposeSMatrix Status main() {TSMatrix M;TSMatrix T;printf("請輸入原矩陣:\n");printf("行數、列數: ");scanf_s("%d%d", &M.mu, &M.nu);printf("元素總數: ");scanf_s("%d", &M.tu);printf("輸入各個對應壓縮值:\n");for (int i = 1; i <= M.tu; ++i)scanf_s("%d%d%d", &M.data[i].i, &M.data[i].j, &M.data[i].e);FastTransposeSMatrix(M, T);printf("轉置后行數、列數、元素總數非別為:\n%d %d %d\n\n", T.mu, T.nu, T.tu);printf("值為:\n");for (int t = 1; t <= T.tu; ++t)printf("%d %d %d\n", T.data[t].i, T.data[t].j, T.data[t].e);system("pause");return OK; }
運行結果如下:


和下面這圖是不是一模一樣




總結

以上是生活随笔為你收集整理的5.3矩阵的压缩存储(稀疏矩阵转置和快速转置)的全部內容,希望文章能夠幫你解決所遇到的問題。

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