[数据结构]第五章-数组和广义表(读书笔记2)
2013-03-25 06:48
344 查看
第五章-数组和广义表
5.3.2 稀疏矩阵
十字链表:是有向图的另一种链式存储结构。当矩阵的非零元个数和位置在操作过程中变化较大时,就不宜采用顺序存储结构来表示三元组的线性表。对这种类型的矩阵,采用链式存储结构表示三元组的线性表更为恰当。在链表中,每个非零元可用一个含5个域的结点表示,其中i,j和e这三个域分别表示该非零元所在的行,列和非零元的值,向右域right用以链接同一行中下一个非零元,向下域down用以链接同一列中下一个非零元。每个非零元既是某个行链表中的一个结点,又是某个列链表中的一个结点,整个矩阵构成了一个十字交叉的链表,故称这样的存储结构为十字链表。
![](http://img.my.csdn.net/uploads/201303/25/1364165603_3104.png)
5.3.2 稀疏矩阵
十字链表:是有向图的另一种链式存储结构。当矩阵的非零元个数和位置在操作过程中变化较大时,就不宜采用顺序存储结构来表示三元组的线性表。对这种类型的矩阵,采用链式存储结构表示三元组的线性表更为恰当。在链表中,每个非零元可用一个含5个域的结点表示,其中i,j和e这三个域分别表示该非零元所在的行,列和非零元的值,向右域right用以链接同一行中下一个非零元,向下域down用以链接同一列中下一个非零元。每个非零元既是某个行链表中的一个结点,又是某个列链表中的一个结点,整个矩阵构成了一个十字交叉的链表,故称这样的存储结构为十字链表。
![](http://img.my.csdn.net/uploads/201303/25/1364165603_3104.png)
typedef int ElemType; /* 稀疏矩阵的十字链表存储表示 */ typedef struct OLNode{ int i,j; /* 该非零元的行和列下标 */ ElemType e; /* 非零元素值 */ struct OLNode *right,*down; /* 该非零元所在行表和列表的后继链域 */ }OLNode,*OLink; typedef struct{ OLink *rhead,*chead; /* 行和列链表头指针向量基址,由CreatSMatrix_OL()分配 */ int mu,nu,tu; /* 稀疏矩阵的行数、列数和非零元个数 */ }CrossList; Status InitSMatrix(CrossList *M) /* 加 */ { /* 初始化M(CrossList类型的变量必须初始化,否则创建、复制矩阵将出错) */ (*M).chead = (*M).rhead = NULL; (*M).mu = (*M).nu = (*M).tu = 0; return OK; } Status DestroySMatrix(CrossList *M) { /* 初始条件: 稀疏矩阵M存在。操作结果: 销毁稀疏矩阵M */ int i; OLNode *p,*q; for(i=1; i <= (*M).mu; i++){ /* 按行释放结点 */ p=*((*M).rhead+i); while(p){ q = p; p = p->right; free(q); } } free((*M).rhead); free((*M).chead); (*M).rhead = (*M).chead = NULL; (*M).mu = (*M).nu = (*M).tu=0; return OK; } Status PrintSMatrix(CrossList M) { /* 初始条件: 稀疏矩阵M存在。操作结果: 按行或按列输出稀疏矩阵M */ int i,j; OLink p; printf("%d行%d列%d个非零元素\n",M.mu,M.nu,M.tu); printf("请输入选择(1.按行输出 2.按列输出): "); scanf("%d",&i); switch(i) { case 1: for(j = 1 ;j <= M.mu ;j++){ p = M.rhead[j]; while(p){ printf("%d行%d列值为%d\n",p->i,p->j,p->e); p = p->right; } } break; case 2: for(j=1 ;j <= M.nu; j++){ p = M.chead[j]; while(p){ printf("%d行%d列值为%d\n",p->i, p->j, p->e); p = p->down; } } break; } return OK; } Status CreateSMatrix(CrossList *M) { /* 创建稀疏矩阵M,采用十字链表存储表示。算法5.4 */ int i,j,k,m,n,t; ElemType e; OLNode *p,*q; if( (*M).rhead ){ DestroySMatrix(M); } printf("请输入稀疏矩阵的行数 列数 非零元个数: "); scanf("%d%d%d",&m, &n, &t); (*M).mu = m; (*M).nu = n; (*M).tu = t; (*M).rhead = (OLink*)malloc((m + 1) * sizeof(OLink)); if(!(*M).rhead){ exit(OVERFLOW); } (*M).chead = (OLink*)malloc((n + 1) * sizeof(OLink)); if(!(*M).chead){ exit(OVERFLOW); } for(k = 1;k <= m; k++){ /* 初始化行头指针向量;各行链表为空链表 */ (*M).rhead[k] = NULL; } for(k = 1;k <= n; k++){ /* 初始化列头指针向量;各列链表为空链表 */ (*M).chead[k] = NULL; } printf("请按任意次序输入%d个非零元的行 列 元素值:\n", (*M).tu); for(k = 0; k < t; k++){ scanf("%d%d%d",&i, &j, &e); p = (OLNode*)malloc(sizeof(OLNode)); if(!p){ exit(OVERFLOW); } p->i = i; p->j = j; p->e = e; /* 生成结点 */ if ((*M).rhead[i] == NULL || (*M).rhead[i]->j > j ){/* p插在该行的第一个结点处 */ 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 ((*M).chead[j] == NULL || (*M).rhead[j]->i > i ){/* p插在该列的第一个结点处 */ 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 OK; } Status CopySMatrix(CrossList M,CrossList *T) { /* 初始条件: 稀疏矩阵M存在。操作结果: 由稀疏矩阵M复制得到T */ int i; OLink p,q,q1,q2; if((*T).rhead){ DestroySMatrix(T); } (*T).mu = M.mu; (*T).nu = M.nu; (*T).tu = M.tu; (*T).rhead = (OLink*)malloc((M.mu + 1) * sizeof(OLink)); if(!(*T).rhead){ exit(OVERFLOW); } (*T).chead = (OLink*)malloc((M.nu + 1) * sizeof(OLink)); if(!(*T).chead){ exit(OVERFLOW); } for(i = 1; i <= M.mu; i++){ /* 初始化矩阵T的行头指针向量;各行链表为空链表 */ (*T).rhead[i] = NULL; } for(i = 1;i <= M.nu; i++){ /* 初始化矩阵T的列头指针向量;各列链表为空链表 */ (*T).chead[i] = NULL; } for(i = 1; i <= M.mu; i++){ /* 按行复制 */ p = M.rhead[i]; while(p){/*没到行尾*/ q = (OLNode*)malloc(sizeof(OLNode)); /* 生成结点 */ if(!q){ exit(OVERFLOW); } q->i = p->i; /* 给结点赋值 */ q->j = p->j; q->e = p->e; if(!(*T).rhead[i]){ /* 插在行表头 */ (*T).rhead[i] = q1 = q; } else{ /* 插在行表尾 */ q1 = (*T).rhead[i]; while(q1->right){ q1 = q1->right; } q1->right = q; q->right = NULL; } if(!(*T).chead[q->j]){ /* 插在列表头 */ (*T).chead[q->j] = q; q->down = NULL; } else{ /* 插在列表尾 */ q2 = (*T).chead[q->j]; while(q2->down){ q2 = q2->down; } q2->down = q; q->down = NULL; } p = p->right; }//while q->right = NULL; } return OK; } Status AddSMatrix(CrossList M,CrossList N,CrossList *Q) { /* 初始条件: 稀疏矩阵M与N的行数和列数对应相等。 */ /* 操作结果: 求稀疏矩阵的和Q=M+N */ int i,k; OLink p,pq,pm,pn; OLink *col; if( M.mu != N.mu || M.nu != N.nu ){ printf("两个矩阵不是同类型的,不能相加\n"); exit(OVERFLOW); } (*Q).mu = M.mu; /* 初始化Q矩阵 */ (*Q).nu = M.nu; (*Q).tu = 0; /* 元素个数的初值 */ (*Q).rhead = (OLink*)malloc(((*Q).mu + 1)*sizeof(OLink)); if(!(*Q).rhead){ exit(OVERFLOW); } (*Q).chead = (OLink*)malloc(((*Q).nu + 1)*sizeof(OLink)); if(!(*Q).chead){ exit(OVERFLOW); } for(k = 1;k <= (*Q).mu; k++){ /* 初始化Q的行头指针向量;各行链表为空链表 */ (*Q).rhead[k] = NULL; } for(k = 1;k <= (*Q).nu; k++){ /* 初始化Q的列头指针向量;各列链表为空链表 */ (*Q).chead[k] = NULL; } col = (OLink*)malloc(((*Q).nu + 1)*sizeof(OLink)); /* 生成指向列的最后结点的数组 */ if(!col){ exit(OVERFLOW); } for(k = 1;k <= (*Q).nu; k++){ /* 赋初值 */ col[k] = NULL; } for(i = 1; i <= M.mu; i++){ /* 按行的顺序相加 */ pm = M.rhead[i]; /* pm指向矩阵M的第i行的第1个结点 */ pn = N.rhead[i]; /* pn指向矩阵N的第i行的第1个结点 */ while( pm && pn ){ /* pm和pn均不空 */ /* 矩阵M当前结点的列小于矩阵N当前结点的列 */ if( pm->j < pn->j ){ p = (OLink)malloc(sizeof(OLNode)); /* 生成矩阵Q的结点 */ if(!p){ exit(OVERFLOW); } (*Q).tu++; /* 非零元素数加1 */ p->i = i; /* 给结点赋值 */ p->j = pm->j; p->e = pm->e; p->right = NULL; pm = pm->right; /* pm指针向右移 */ } /* 矩阵M当前结点的列大于矩阵N当前结点的列 */ else if( pm->j > pn->j ){ p = (OLink)malloc(sizeof(OLNode)); /* 生成矩阵Q的结点 */ if(!p){ exit(OVERFLOW); } (*Q).tu++; /* 非零元素数加1 */ p->i = i; /* 给结点赋值 */ p->j = pn->j; p->e = pn->e; p->right = NULL; pn = pn->right; /* pn指针向右移 */ } /* 矩阵M、N当前结点的列相等且两元素之和不为0 */ else if(pm->e + pn->e != 0){ p = (OLink)malloc(sizeof(OLNode)); /* 生成矩阵Q的结点 */ if(!p){ exit(OVERFLOW); } (*Q).tu++; /* 非零元素数加1 */ p->i = i;/* 给结点赋值 */ p->j = j; p->e = pm->e + pn->e; p->right = NULL; pm = pm->right; /* pm指针向右移 */ pn = pn->right; /* pn指针向右移 */ } /* 矩阵M、N当前结点的列相等且两元素之和为0 */ else{ pm = pm->right; /* pm指针向右移 */ pn = pn->right; /* pn指针向右移 */ continue; } if((*Q).rhead[i] == NULL){ /* p为该行的第1个结点 */ (*Q).rhead[i] = pq = p; /* p插在该行的表头且pq指向p(该行的最后一个结点) */ } else{/* 插在pq所指结点之后 */ pq->right = p; /* 完成行插入 */ pq = pq->right; /* pq指向该行的最后一个结点 */ } if((*Q).chead[p->j] == NULL){ /* p为该列的第1个结点 */ (*Q).chead[p->j] = col[p->j] = p; /* p插在该列的表头且col[p->j]指向p */ } else{ /* 插在col[p->]所指结点之后 */ col[p->j]->down = p; /* 完成列插入 */ col[p->j] = col[p->j]->down; /* col[p->j]指向该列的最后一个结点 */ } }//while while(pm){ /* 将矩阵M该行的剩余元素插入矩阵Q */ p = (OLink)malloc(sizeof(OLNode)); /* 生成矩阵Q的结点 */ if(!p){ exit(OVERFLOW); } (*Q).tu++; /* 非零元素数加1 */ p->i = i; /* 给结点赋值 */ p->j = pm->j; p->e = pm->e; p->right = NULL; pm = pm->right; /* pm指针向右移 */ if((*Q).rhead[i] == NULL){ /* p为该行的第1个结点 */ (*Q).rhead[i] = pq = p; /* p插在该行的表头且pq指向p(该行的最后一个结点) */ } else{ /* 插在pq所指结点之后 */ pq->right = p; /* 完成行插入 */ pq = pq->right; /* pq指向该行的最后一个结点 */ } if((*Q).chead[p->j]==NULL){ /* p为该列的第1个结点 */ (*Q).chead[p->j] = col[p->j] = p; /* p插在该列的表头且col[p->j]指向p */ } else{ /* 插在col[p->j]所指结点之后 */ col[p->j]->down = p; /* 完成列插入 */ col[p->j] = col[p->j]->down; /* col[p->j]指向该列的最后一个结点 */ } }//while(pm) while(pn) /* 将矩阵N该行的剩余元素插入矩阵Q */ { p=(OLink)malloc(sizeof(OLNode)); /* 生成矩阵Q的结点 */ if(!p){ exit(OVERFLOW); } (*Q).tu++; /* 非零元素数加1 */ p->i = i; /* 给结点赋值 */ p->j = pn->j; p->e = pn->e; p->right = NULL; pn = pn->right; /* pm指针向右移 */ if((*Q).rhead[i] == NULL){ /* p为该行的第1个结点 */ (*Q).rhead[i] = pq = p; /* p插在该行的表头且pq指向p(该行的最后一个结点) */ else{ /* 插在pq所指结点之后 */ pq->right = p; /* 完成行插入 */ pq = pq->right; /* pq指向该行的最后一个结点 */ } if((*Q).chead[p->j] == NULL){ /* p为该列的第1个结点 */ (*Q).chead[p->j] = col[p->j] = p; /* p插在该列的表头且col[p->j]指向p */ } else{ /* 插在col[p->j]所指结点之后 */ col[p->j]->down=p; /* 完成列插入 */ col[p->j]=col[p->j]->down; /* col[p->j]指向该列的最后一个结点 */ }//while(pn) `}//if } int _tmain(int argc, _TCHAR* argv[]) { return 0; }
相关文章推荐
- [数据结构]第五章-数组和广义表(读书笔记3)
- 数据结构 第五章 数组和广义表
- 数据结构第五章--数组和广义表
- 数据结构——数组、矩阵与广义表
- 数据结构习题之多维数组和广义表
- 5-5-广义表(头尾链表存储表示)-数组和广义表-第5章-《数据结构》课本源码-严蔚敏吴伟民版
- c语言版数据结构(奇迹冬瓜)-数组和广义表(十字链表稀疏矩阵的加法)
- 第五章 数组和广义表练习题
- 2015年大二上-数据结构-数组与广义表(2)-2.压缩存储的对称矩阵的运算
- 5-2-三元组顺序表(稀疏矩阵)-数组和广义表-第5章-《数据结构》课本源码-严蔚敏吴伟民版
- 2015年大二上-数据结构-数组与广义表(3)-2.稀疏矩阵的三元组表示
- 5-6-广义表(扩展线性链表存储表示)-数组和广义表-第5章-《数据结构》课本源码-严蔚敏吴伟民版
- 数据结构 第四章 串、数组和广义表
- 数据结构学习-数组和广义表
- 数据结构_数组与广义表_广义表的建立、遍历、复制、求深度
- 数据结构复习-数组、广义表、递归、哈夫曼数/并查集
- (数据结构第五章)广义表的头尾链表存储表示
- 第九周 数据结构实践项目——数组和广义表【项目3.2-- 稀疏矩阵相加】
- (数据结构第五章)数组实现
- 5-4-十字链表(稀疏矩阵)-数组和广义表-第5章-《数据结构》课本源码-严蔚敏吴伟民版