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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

数据结构 稀疏矩阵的实现方法

發(fā)布時(shí)間:2025/3/21 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数据结构 稀疏矩阵的实现方法 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

稀疏矩陣的實(shí)現(xiàn)

什么是稀疏矩陣,怎么定義才是稀疏矩陣?假設(shè)在m x n的矩陣中,有t個(gè)不為0的元素。令z=t/(m x n),若z<=0.05則稱此矩陣為稀疏矩陣。由于稀疏矩陣的非0元素較少,所以如果用大容量存儲(chǔ)必定會(huì)造成內(nèi)存浪費(fèi),因此只需存儲(chǔ)非0元素值即可,以下列出了常用的三種存儲(chǔ)稀疏矩陣的方法。

三元組順序表

三元組順序表的實(shí)現(xiàn)用順序存儲(chǔ)結(jié)構(gòu)來實(shí)現(xiàn)。定義一個(gè)數(shù)組的結(jié)構(gòu)體,存儲(chǔ)的是三元組(即由 3 部分?jǐn)?shù)據(jù)組成的集合),組中數(shù)據(jù)分別表示(行標(biāo),列標(biāo),元素值)。結(jié)構(gòu)體的實(shí)現(xiàn)如下:

//三元組結(jié)構(gòu)體 typedef struct {int i,j;//行標(biāo)i,列標(biāo)jint data;//元素值 }triple; //矩陣的結(jié)構(gòu)表示 typedef struct {triple data[number];//存儲(chǔ)該矩陣中所有非0元素的三元組int n,m,num;//n和m分別記錄矩陣的行數(shù)和列數(shù),num記錄矩陣中所有的非0元素的個(gè)數(shù) }TSMatrix;


如上圖所示即為依次再數(shù)組中插入的 三元表。具體實(shí)現(xiàn)過程如下所示:

#include <stdio.h> #define MAXSIZE 100 #define OK 1 #define ERROR 0 #define ELEMTYPE inttypedef struct {int i; //行int j; //列ELEMTYPE e; //元素 }Triple; typedef struct {Triple data[MAXSIZE+1];int mu, nu, tu; }TSmatrix; void display(TSmatrix *s); int main(void) {TSmatrix s;s.mu = 3;s.nu = 3;s.tu = 3;s.data[0].i = 3;s.data[0].j = 3;s.data[0].e = 6;s.data[1].i = 2;s.data[1].j = 3;s.data[1].e = 8;s.data[2].i = 2;s.data[2].j = 1;s.data[2].e = 4;display(&s);getchar();return 0; }void display(TSmatrix *s) {for (int i = 1; i <= s->mu; i++){for (int j = 1; j <= s->nu; j++){int value = 0; //用來判斷是否到了指定的(i,j)位置for (int k = 0; k < s->tu; k++)//遍歷數(shù)組中的三元表值{if (s->data[k].i == i && s->data[k].j == j) //若遍歷至指定(i,j)就打印元素值{value = 1;printf("%d ", s->data[k].e);break;}}if(value==0) //若不為三元表中存儲(chǔ)的值就打印0printf("%d ", 0);}printf("\n");} }


結(jié)果如上圖所示,檢查矩陣可知打印的位置是沒有問題的。
如上所示的方法能夠?qū)崿F(xiàn)稀疏矩陣的存儲(chǔ),但是在數(shù)據(jù)提取方面效率比較低,現(xiàn)在只是3x3的矩陣可能看不出來,但若是m和n都以千萬計(jì)的情況下稀疏矩陣中的非0元素個(gè)數(shù)近似于n,那么時(shí)間復(fù)雜度就會(huì)達(dá)到O(m x n xn),這將非常浪費(fèi)時(shí)間。因此在此方法上改進(jìn)有了下面的方法。

行邏輯鏈接的順序表

行邏輯鏈接順序表示基于上種方法的改進(jìn),在上面的基礎(chǔ)上再增加一個(gè)數(shù)組用來存儲(chǔ)用來用于存儲(chǔ)三元表的數(shù)組中每一行第一個(gè)非0元素的位置,這樣就無需遍歷整個(gè)三元表數(shù)組,只需要遍歷對(duì)應(yīng)行的數(shù)據(jù)就可以了,大大提高了效率。


使用數(shù)組 rpos 記錄矩陣中每行第一個(gè)非 0 元素在一維數(shù)組中的存儲(chǔ)位置。遍歷的具體過程如下所示:
由 rpos 數(shù)組可知,第一行首個(gè)非 0 元素位于data[1],因此在遍歷此行時(shí),可以直接從第 data[1] 的位置開始,一直遍歷到下一行首個(gè)非 0 元素所在的位置(data[3]之前;
同樣遍歷第二行時(shí),由 rpos 數(shù)組可知,此行首個(gè)非 0 元素位于 data[3],因此可以直接從第 data[3] 開始,一直遍歷到下一行首個(gè)非 0 元素所在的位置(data[4])之前;
遍歷第三行時(shí),由 rpos 數(shù)組可知,此行首個(gè)非 0 元素位于 data[4],由于這是矩陣的最后一行,因此一直遍歷到 rpos 數(shù)組結(jié)束即可(也就是 data[tu],tu 指的是矩陣非 0 元素的總個(gè)數(shù))。

#include <stdio.h> #define MAXSIZE 100 #define MAXSD 100 #define ELEMTYPE inttypedef struct {int i;int j;ELEMTYPE e; }Triple; typedef struct {Triple data[MAXSIZE];int rpos[MAXSD]; //定義rpos數(shù)組用于存儲(chǔ)每一行第一個(gè)非0元素int mu, nu, tu; }RLSmatrix; void display(RLSmatrix *s); int main(void) {RLSmatrix s;s.mu = 4;s.nu = 3;s.tu = 4;s.data[1].i = 1;s.data[1].j = 1;s.data[1].e = 3;s.data[2].i = 2;s.data[2].j = 2;s.data[2].e = 4;s.data[3].i = 3;s.data[3].j = 3;s.data[3].e = 6;s.data[4].i = 4;s.data[4].j = 3;s.data[4].e = 3;s.rpos[1] = 1;s.rpos[2] = 2;s.rpos[3] = 3;s.rpos[4] = 4;display(&s);getchar();return 0;}void display(RLSmatrix *s) {for (int i = 1; i <= s->mu; i++){for (int j = 1; j <= s->nu; j++){int value = 0;if(i+1<=s->mu) //假設(shè)一共i行則前面的i-1行遍歷對(duì)應(yīng)行的元素{for (int k = s->rpos[i]; k < s->rpos[i + 1]; k++) //遍歷數(shù)組中對(duì)應(yīng)行的非0元素即可{if (s->data[k].i == i && s->data[k].j == j) {value = 1;printf("%d ", s->data[k].e);break;}if (value == 0)printf("0 ");}}else //最后一行只需遍歷到最后一個(gè)非0元素即可{for (int k = s->rpos[i]; k <=s->tu; k++){if (s->data[k].i == i && s->data[k].j == j){value = 1;printf("%d ", s->data[k].e);break;}if (value == 0)printf("0 ");}}}printf("\n");} }

十字鏈表法存儲(chǔ)稀疏矩陣

上面兩種存儲(chǔ)方式用于固定存儲(chǔ)時(shí)可以很好的起作用,但是當(dāng)要涉及非0元素的插入或者刪除的時(shí)候回引起元素值的移動(dòng),例如兩矩陣相加的操作,這種時(shí)候用鏈?zhǔn)酱鎯?chǔ)表示三元組更為恰當(dāng),該存儲(chǔ)方式采用的是 “鏈表+數(shù)組” 結(jié)構(gòu)。


由上圖可以看到,非0元素用一個(gè)含有五個(gè)域的節(jié)點(diǎn)表示,兩個(gè)指針與分別用來指向同一列和同一行的元素。再用兩個(gè)存儲(chǔ)行鏈表和列鏈表的一維數(shù)組存儲(chǔ)這些鏈表。每一個(gè)非0元既是某行鏈表的一個(gè)節(jié)點(diǎn),又是列鏈表的一個(gè)節(jié)點(diǎn)。整個(gè)矩陣構(gòu)成了一個(gè)十字交叉的鏈表。

#include<stdio.h> #include<stdlib.h> typedef struct OLNode {int i, j, e; //矩陣三元組i代表行 j代表列 e代表當(dāng)前位置的數(shù)據(jù)struct OLNode *right, *down; //指針域 右指針 下指針 }OLNode, *OLink; typedef struct {OLink *rhead, *chead; //行和列鏈表頭指針int mu, nu, tu; //矩陣的行數(shù),列數(shù)和非零元的個(gè)數(shù) }CrossList; CrossList CreateMatrix_OL(CrossList M); void display(CrossList M); int main() {CrossList M;M.rhead = NULL;M.chead = NULL;M = CreateMatrix_OL(M);printf("輸出矩陣M:\n");display(M);return 0; } CrossList CreateMatrix_OL(CrossList M) {int m, n, t;int i, j, e;OLNode *p, *q;printf("輸入矩陣的行數(shù)、列數(shù)和非0元素個(gè)數(shù):");scanf("%d%d%d", &m, &n, &t);M.mu = m;M.nu = n;M.tu = t;if (!(M.rhead = (OLink*)malloc((m + 1) * sizeof(OLink))) || !(M.chead = (OLink*)malloc((n + 1) * sizeof(OLink)))){printf("初始化矩陣失敗");exit(0);}for (i = 1; i <= m; i++){M.rhead[i] = NULL;}for (j = 1; j <= n; j++){M.chead[j] = NULL;}for (scanf("%d%d%d", &i, &j, &e); 0 != i; scanf("%d%d%d", &i, &j, &e)) {if (!(p = (OLNode*)malloc(sizeof(OLNode)))){printf("初始化三元組失敗");exit(0);}p->i = i;p->j = j;p->e = e;//鏈接到行的指定位置if (NULL == M.rhead[i] || M.rhead[i]->j > j){p->right = M.rhead[i];M.rhead[i] = p;}else{for (q = M.rhead[i]; (q->right) && q->right->j < j; q = q->right);p->right = q->right;q->right = p;}//鏈接到列的指定位置if (NULL == M.chead[j] || M.chead[j]->i > i){p->down = M.chead[j];M.chead[j] = p;}else{for (q = M.chead[j]; (q->down) && q->down->i < i; q = q->down);p->down = q->down;q->down = p;}}return M; } void display(CrossList M) {for (int i = 1; i <= M.nu; i++){if (NULL != M.chead[i]){OLink p = M.chead[i];while (NULL != p){printf("%d\t%d\t%d\n", p->i, p->j, p->e);p = p->down;}}} }

總結(jié)

以上是生活随笔為你收集整理的数据结构 稀疏矩阵的实现方法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。