用十字链表实现导纳矩阵的存储
十字链表的存储与运算
⼗字链表的存储与运算#include#includetypedef int ElemType;// 稀疏矩阵的⼗字链表存储表⽰typedef struct OLNode{int i,j; // 该⾮零元的⾏和列下标ElemType e; // ⾮零元素值struct OLNode *right,*down; // 该⾮零元所在⾏表和列表的后继链域}OLNode, *OLink;typedef struct// ⾏和列链表头指针向量基址,由CreatSMatrix_OL()分配{OLink *rhead, *chead;int mu, nu, tu; // 稀疏矩阵的⾏数、列数和⾮零元个数}CrossList;// 初始化M(CrossList类型的变量必须初始化,否则创建、复制矩阵将出错) int InitSMatrix(CrossList *M) {(*M).rhead=(*M).chead=NULL;(*M).mu=(*M).nu=(*M).tu=0;return 1;}// 销毁稀疏矩阵Mint DestroySMatrix(CrossList *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).chead);(*M).rhead=(*M).chead=NULL;(*M).mu=(*M).nu=(*M).tu=0;return 1;}// 创建稀疏矩阵M,采⽤⼗字链表存储表⽰。
int CreateSMatrix(CrossList *M){int i,j,k,m,n,t;ElemType e;OLNode *p,*q;if((*M).rhead)DestroySMatrix(M);printf("请输⼊稀疏矩阵的⾏数列数⾮零元个数:(space) ");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(0);//初始化列链表头(*M).chead=(OLink*)malloc((n+1)*sizeof(OLink));if(!(*M).chead)exit(0);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{if(!p)exit(0);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).chead[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;}}// 按⾏或按列输出稀疏矩阵Mint PrintSMatrix(CrossList 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;}}}return 1;int CopySMatrix(CrossList M,CrossList *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(0);(*T).chead=(OLink*)malloc((M.nu+1)*sizeof(OLink));if(!(*T).chead)exit(0);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(0);q->i=p->i; // 给结点赋值q->j=p->j;q->e=p->e;if(!(*T).rhead[i]) // 插在⾏表头(*T).rhead[i]=q1=q;else // 插在⾏表尾q1=q1->right=q;if(!(*T).chead[q->j]) // 插在列表头q->down=NULL;}else // 插在列表尾{q2=(*T).chead[q->j];while(q2->down)q2=q2->down;q2->down=q;q->down=NULL;}p=p->right;}q->right=NULL;}return 1;}// 求稀疏矩阵的和Q=M+Nint AddSMatrix(CrossList M,CrossList N,CrossList *Q) {int i,k;OLink p,pq,pm,pn;OLink *col;if(M.mu!=N.mu||M.nu!=N.nu){printf("两个矩阵不是同类型的,不能相加\n");exit(0);}(*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(0);exit(0);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(0);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均不空{if(pm->jj) // 矩阵M当前结点的列⼩于矩阵N当前结点的列{p=(OLink)malloc(sizeof(OLNode)); // ⽣成矩阵Q的结点if(!p)exit(0);(*Q).tu++; // ⾮零元素数加1p->i=i; // 给结点赋值p->j=pm->j;p->e=pm->e;p->right=NULL;pm=pm->right; // pm指针向右移}else if(pm->j>pn->j)// 矩阵M当前结点的列⼤于矩阵N当前结点的列{p=(OLink)malloc(sizeof(OLNode)); // ⽣成矩阵Q的结点if(!p)exit(0);(*Q).tu++; // ⾮零元素数加1p->e=pn->e;p->right=NULL;pn=pn->right; // pn指针向右移}// 矩阵M、N当前结点的列相等且两元素之和不为0 else if(pm->e+pn->e){p=(OLink)malloc(sizeof(OLNode)); // ⽣成矩阵Q的结点if(!p)exit(0);(*Q).tu++; // ⾮零元素数加1p->i=i; // 给结点赋值p->j=pn->j;p->e=pm->e+pn->e;p->right=NULL;pm=pm->right; // pm指针向右移pn=pn->right; // pn指针向右移}else // 矩阵M、N当前结点的列相等且两元素之和为0 {pm=pm->right; // pm指针向右移pn=pn->right; // pn指针向右移continue;}if((*Q).rhead[i]==NULL) // p为该⾏的第1个结点// p插在该⾏的表头且pq指向p(该⾏的最后⼀个结点) (*Q).rhead[i]=pq=p;else // 插在pq所指结点之后{pq->right=p; // 完成⾏插⼊pq=pq->right; // pq指向该⾏的最后⼀个结点}if((*Q).chead[p->j]==NULL) // p为该列的第1个结点// p插在该列的表头且col[p->j]指向pcol[p->j]->down=p; // 完成列插⼊// col[p->j]指向该列的最后⼀个结点col[p->j]=col[p->j]->down;}}while(pm) // 将矩阵M该⾏的剩余元素插⼊矩阵Q{p=(OLink)malloc(sizeof(OLNode)); // ⽣成矩阵Q的结点if(!p)exit(0);(*Q).tu++; // ⾮零元素数加1p->i=i; // 给结点赋值p->j=pm->j;p->e=pm->e;p->right=NULL;pm=pm->right; // pm指针向右移if((*Q).rhead[i] == NULL) // p为该⾏的第1个结点// p插在该⾏的表头且pq指向p(该⾏的最后⼀个结点) (*Q).rhead[i] = pq = p;else // 插在pq所指结点之后{pq->right=p; // 完成⾏插⼊pq=pq->right; // pq指向该⾏的最后⼀个结点}if((*Q).chead[p->j] == NULL) // p为该列的第1个结点// p插在该列的表头且col[p->j]指向p(*Q).chead[p->j] = col[p->j] = p;else // 插在col[p->j]所指结点之后{col[p->j]->down=p; // 完成列插⼊// col[p->j]指向该列的最后⼀个结点col[p->j]=col[p->j]->down;}p=(OLink)malloc(sizeof(OLNode)); // ⽣成矩阵Q的结点if(!p)exit(0);(*Q).tu++; // ⾮零元素数加1p->i=i; // 给结点赋值p->j=pn->j;p->e=pn->e;p->right=NULL;pn=pn->right; // pm指针向右移if((*Q).rhead[i]==NULL) // p为该⾏的第1个结点// p插在该⾏的表头且pq指向p(该⾏的最后⼀个结点)(*Q).rhead[i]=pq=p;else // 插在pq所指结点之后{pq->right=p; // 完成⾏插⼊pq=pq->right; // pq指向该⾏的最后⼀个结点}if((*Q).chead[p->j]==NULL) // p为该列的第1个结点// p插在该列的表头且col[p->j]指向p(*Q).chead[p->j]=col[p->j]=p;else // 插在col[p->j]所指结点之后{col[p->j]->down=p; // 完成列插⼊// col[p->j]指向该列的最后⼀个结点col[p->j]=col[p->j]->down;}}}for(k=1;k<=(*Q).nu;k++)if(col[k]) // k列有结点col[k]->down=NULL; // 令该列最后⼀个结点的down指针为空free(col); return 1;}{int i,k;OLink p,pq,pm,pn;OLink *col;if(M.mu!=N.mu||M.nu!=N.nu){printf("两个矩阵不是同类型的,不能相加\n");exit(0);}(*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(0);(*Q).chead=(OLink*)malloc(((*Q).nu+1)*sizeof(OLink));if(!(*Q).chead)exit(0);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(0);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均不空{if(pm->jj) // 矩阵M当前结点的列⼩于矩阵N当前结点的列{p=(OLink)malloc(sizeof(OLNode)); // ⽣成矩阵Q的结点if(!p)exit(0);(*Q).tu++; // ⾮零元素数加1p->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(0);(*Q).tu++; // ⾮零元素数加1p->i=i; // 给结点赋值p->j=pn->j;p->e=-pn->e;p->right=NULL;pn=pn->right; // pn指针向右移}else if(pm->e-pn->e){// 矩阵M、N当前结点的列相等且两元素之差不为0p=(OLink)malloc(sizeof(OLNode)); // ⽣成矩阵Q的结点if(!p)exit(0);(*Q).tu++; // ⾮零元素数加1p->i=i; // 给结点赋值p->j=pn->j;p->e=pm->e-pn->e;p->right=NULL;pm=pm->right; // pm指针向右移pn=pn->right; // pn指针向右移}else // 矩阵M、N当前结点的列相等且两元素之差为0 {pm=pm->right; // pm指针向右移pn=pn->right; // pn指针向右移continue;}if((*Q).rhead[i]==NULL) // p为该⾏的第1个结点// p插在该⾏的表头且pq指向p(该⾏的最后⼀个结点) (*Q).rhead[i]=pq=p;else // 插在pq所指结点之后{pq->right=p; // 完成⾏插⼊pq=pq->right; // pq指向该⾏的最后⼀个结点}if((*Q).chead[p->j]==NULL) // p为该列的第1个结点// p插在该列的表头且col[p->j]指向p(*Q).chead[p->j]=col[p->j]=p;else // 插在col[p->]所指结点之后{col[p->j]->down=p; // 完成列插⼊// col[p->j]指向该列的最后⼀个结点col[p->j]=col[p->j]->down;}}while(pm) // 将矩阵M该⾏的剩余元素插⼊矩阵Q{p=(OLink)malloc(sizeof(OLNode)); // ⽣成矩阵Q的结点if(!p)exit(0);(*Q).tu++; // ⾮零元素数加1p->i=i; // 给结点赋值p->j=pm->j;p->e=pm->e;p->right=NULL;pm=pm->right; // pm指针向右移if((*Q).rhead[i]==NULL) // p为该⾏的第1个结点// p插在该⾏的表头且pq指向p(该⾏的最后⼀个结点) (*Q).rhead[i]=pq=p;else // 插在pq所指结点之后{pq->right=p; // 完成⾏插⼊pq=pq->right; // pq指向该⾏的最后⼀个结点}if((*Q).chead[p->j]==NULL) // p为该列的第1个结点// p插在该列的表头且col[p->j]指向p(*Q).chead[p->j]=col[p->j]=p;else // 插在col[p->j]所指结点之后{col[p->j]->down=p; // 完成列插⼊// col[p->j]指向该列的最后⼀个结点col[p->j]=col[p->j]->down;}}while(pn) // 将矩阵N该⾏的剩余元素插⼊矩阵Q{p=(OLink)malloc(sizeof(OLNode)); // ⽣成矩阵Q的结点if(!p)exit(0);(*Q).tu++; // ⾮零元素数加1p->i=i; // 给结点赋值p->j=pn->j;p->e=-pn->e;p->right=NULL;pn=pn->right; // pm指针向右移if((*Q).rhead[i]==NULL) // p为该⾏的第1个结点// p插在该⾏的表头且pq指向p(该⾏的最后⼀个结点) (*Q).rhead[i]=pq=p;else // 插在pq所指结点之后{pq->right=p; // 完成⾏插⼊pq=pq->right; // pq指向该⾏的最后⼀个结点}if((*Q).chead[p->j]==NULL) // p为该列的第1个结点// p插在该列的表头且col[p->j]指向p(*Q).chead[p->j]=col[p->j]=p;else // 插在col[p->j]所指结点之后{col[p->j]->down=p; // 完成列插⼊// col[p->j]指向该列的最后⼀个结点col[p->j]=col[p->j]->down;}}}for(k=1;k<=(*Q).nu;k++)if(col[k]) // k列有结点col[k]->down=NULL; // 令该列最后⼀个结点的down指针为空free(col);return 1;}// 求稀疏矩阵乘积Q=M*Nint MultSMatrix(CrossList M,CrossList N,CrossList *Q){int i,j,e;OLink q,p0,q0,q1,q2;InitSMatrix(Q);(*Q).mu=M.mu;(*Q).nu=N.nu;(*Q).tu=0;(*Q).rhead=(OLink*)malloc(((*Q).mu+1)*sizeof(OLink));if(!(*Q).rhead)exit(0);(*Q).chead=(OLink*)malloc(((*Q).nu+1)*sizeof(OLink));if(!(*Q).chead)exit(0);for(i=1;i<=(*Q).mu;i++) // 初始化矩阵Q的⾏头指针向量;各⾏链表为空链表(*Q).rhead[i]=NULL; for(i=1;i<=(*Q).nu;i++) // 初始化矩阵Q的列头指针向量;各列链表为空链表(*Q).chead[i]=NULL; for(i=1;i<=(*Q).mu;i++)for(j=1;j<=(*Q).nu;j++)p0=M.rhead[i];q0=N.chead[j];e=0;while(p0&&q0){if(q0->ij)q0=q0->down; // 列指针后移else if(q0->i>p0->j)p0=p0->right; // ⾏指针后移else // q0->i==p0->j{e+=p0->e*q0->e; // 乘积累加q0=q0->down; // ⾏列指针均后移p0=p0->right;}}if(e) // 值不为0{(*Q).tu++; // ⾮零元素数加1q=(OLink)malloc(sizeof(OLNode)); // ⽣成结点if(!q) // ⽣成结点失败exit(0);q->i=i; // 给结点赋值q->j=j;q->e=e;q->right=NULL;q->down=NULL;if(!(*Q).rhead[i]) // ⾏表空时插在⾏表头(*Q).rhead[i]=q1=q;else // 否则插在⾏表尾q1=q1->right=q;if(!(*Q).chead[j]) // 列表空时插在列表头(*Q).chead[j]=q;else // 否则插在列表尾q2=(*Q).chead[j]; // q2指向j⾏第1个结点while(q2->down)q2=q2->down; // q2指向j⾏最后1个结点q2->down=q;}}}return 1;}// 求稀疏矩阵M的转置矩阵Tint TransposeSMatrix(CrossList M,CrossList *T) {int u,i;OLink *head,p,q,r;if((*T).rhead)DestroySMatrix(T);CopySMatrix(M,T); // T=Mu=(*T).mu; // 交换(*T).mu和(*T).nu(*T).mu=(*T).nu;(*T).nu=u;head=(*T).rhead; // 交换(*T).rhead和(*T).chead (*T).rhead=(*T).chead;(*T).chead=head;for(u=1;u<=(*T).mu;u++) // 对T的每⼀⾏{p=(*T).rhead[u]; // p为⾏表头while(p) // 没到表尾,对T的每⼀结点{q=p->down; // q指向下⼀个结点i=p->i; // 交换.i和.jp->i=p->j;p->j=i;r=p->down; // 交换.down.和rightp->down=p->right;p->right=r;p=q; // p指向下⼀个结点}}return 1;}int main(){CrossList A,B,C;InitSMatrix(&A); // CrossList类型的变量在初次使⽤之前必须初始化InitSMatrix(&B);printf("创建矩阵A: ");CreateSMatrix(&A);PrintSMatrix(A);printf("由矩阵A复制矩阵B: ");CopySMatrix(A,&B);PrintSMatrix(B);DestroySMatrix(&B); // CrossList类型的变量在再次使⽤之前必须先销毁printf("销毁矩阵B后:\n"); PrintSMatrix(B);printf("创建矩阵B2:(与矩阵A的⾏、列数相同,⾏、列分别为%d,%d)\n",A.mu,A.nu);CreateSMatrix(&B);PrintSMatrix(B);printf("矩阵C1(A+B): ");AddSMatrix(A,B,&C);PrintSMatrix(C);DestroySMatrix(&C);printf("矩阵C2(A-B): ");SubtSMatrix(A,B,&C);PrintSMatrix(C);DestroySMatrix(&C);printf("矩阵C3(A的转置): ");TransposeSMatrix(A,&C);PrintSMatrix(C);DestroySMatrix(&A);DestroySMatrix(&B);DestroySMatrix(&C);printf("创建矩阵A2: ");CreateSMatrix(&A);PrintSMatrix(A);printf("创建矩阵B3:(⾏数应与矩阵A2的列数相同=%d)\n",A.nu); CreateSMatrix(&B);PrintSMatrix(B);printf("矩阵C5(A*B): ");MultSMatrix(A,B,&C);PrintSMatrix(C);DestroySMatrix(&A);DestroySMatrix(&B);DestroySMatrix(&C);system("pause");return 0;}。
基于十字链表的矩阵运算
数 据 结 构课 程 设 计 报 告日期: 年 月 日122009 30 学 号班 级卫熙 姓 名指 导 教 师 王 平2007级信息与计算科学 20070744044 题目:基于正交链表的矩阵运算说明本组成员名单:卫熙谢武杰孙洋洋王帅吴波组长:卫熙本人承担的课程设计的工作情况:程序的算法设计以及部分功能实现,后期程序调试、测试,主函数的设计。
目录1 任务概述 (3)1.1 问题描述 (3)1.2 编程的基本要求 (3)1.3 程序的主要功能 (3)1.4 编程语言及选择的操作平台 (3)2 概要设计 (4)2.1 数据结构 (4)2.2 总体结构 (4)3 详细设计 (5)3.1 数据结构中的函数 (6)3.2 主函数及其他函数 (7)4 调试分析 (9)4.1调试过程 (9)4.2测试结果 (9)4.2改进设想 (14)5 用户手册 (15)6 总结 (17)参考文献 (18)附件源程序代码清单 (19)1 任务概述1.1 问题描述应用三元组和正交链表存储稀疏矩阵,并实现稀疏矩阵的转置、加法和乘法运算。
1.2 编程的基本要求1)应用三元组和正交链表的数据结构。
2)矩阵运算由正交链表类的成员函数实现,矩阵的输入输出由类的友元重载函数实现。
3)主函数用于实现菜单和调用。
1.3 程序的主要功能1. 按《数据结构课程设计》报告格式所给出的框架撰写。
2. 具体内容应尽量包含文字叙述、图表(表格,框图,流程图,UML图等)和程序代码。
3. 每个同学要提交电子文档和一份打印稿。
1.4 编程语言及选择的操作平台编程语言选用C++程序设计语言。
程序开发平台选用Mcrosoft Visual Studio 6.0的Microsoft Visual C++ 6.0开发环境。
程序运行在DOS界面。
2 概要设计2.1 数据结构稀疏矩阵类(matrix)稀疏矩阵的节点类(node)2.2总体结构说明:表达式i!=0 True,向下执行,False 结束退出3 详细设计3.1 数据结构中的函数(其中函数的实现请参看源代码部分)1) 矩阵结点(matrix)中的函数:Private:friend istream&operator>>(istream&,matrix&);friend ostream&operator<<(ostream&,matrix&);//int Row,Col,Terms,temp; //矩阵的总行数,总列数,和非零元素个数和临时变量;//node*headnode; //稀疏矩阵的总表头public:matrix(int m,int n); //重载构造函数matrix(); //对矩阵进行构造matrix(matrix& T); //拷贝构造函数~matrix(){makeEmpty();} //析构函数void Init(int m,int n); //初始化函数,又来初始化无参构造函数构造的矩阵void makeEmpty(); //清空矩阵void Insert(int m,int n,float p); //插入矩阵元素void Delete(int m,int n); //删除特定行列元素node *Locate(int i); //定位附加头结点matrix transpose(); //矩阵的转置运算matrix Add( matrix b); //两个矩阵相加matrix Mul(matrix b); //两个矩阵相乘matrix &operator=(matrix &T); //重载赋值号2)节点类(node)的函数:node():head(TRUE){ right=down=this;} //建立附加头结点node(element *t){// 建立非零元素结点triple.col=t->col; triple.row=t->row; triple.item=t->item; right=down=this; head=FALSE;}3.2 主函数及其他函数#include"matrix.h"#include<conio.h>void main(){int i;matrix B,B1,B2,C;while(i!=0){cout<<" ----------------基于正交链表的稀疏矩阵的运算-----------------"<<endl<<endl;cout<<" 1.转置 2.加法 3.乘法0.退出程序"<<endl<<endl;cout<<"请选择:";cin>>i; cout<<endl;switch(i){case 0: break;case 1: cout<<" -------稀疏矩阵的转置------\n"<<endl;cout<<"请输入矩阵:"<<endl<<endl;cin>>B;system("cls");cout<<"原矩阵为:"<<endl;cout<<B<<endl;cout<<"转置后为"<<endl;cout<<B.transpose()<<endl; break;case 2: cout<<" --------稀疏矩阵的加法-------\n"<<endl;cout<<"请输入矩阵1:"<<endl<<endl;cin>>B1;cout<<"请输入矩阵2:"<<endl<<endl;cin>>B2;system("cls");cout<<"矩阵1为:"<<endl;cout<<B1<<endl;cout<<"矩阵2为:"<<endl;cout<<B2<<endl;cout<<"两个矩阵之和为:"<<endl;cout<<B1.Add(B2)<<endl;break;case 3: cout<<" --------稀疏矩阵的乘法-------\n"<<endl;cout<<"注意:输入的矩阵必须满足矩阵相乘的条件,并且按顺序输入(即1和2的顺序)\n"<<endl;cout<<"请输入矩阵1:"<<endl;cin>>B1;cout<<"请输入矩阵2:"<<endl;cin>>B2;system("cls");cout<<"矩阵1为:"<<endl;cout<<B1<<endl;cout<<"矩阵2为:"<<endl;cout<<B2<<endl;cout<<"两个矩阵之积为:"<<endl;cout<<B1.Mul(B2)<<endl;break;default:break;}if(i!=0){cout<<"按任意继续......"<<endl; getch();system("cls");}}}//YEAH!!!!终于于31日9:19调试成功了!!!4.1 调试过程再调试过程中,出现最多的问题是控制循环的终止条件,由于指针用的比较多,导致有时用指针做循环终止条件时没有考虑到其值的改变。
十字链表法存储稀疏矩阵
十字链表法存储稀疏矩阵稀疏矩阵是指其中大部分元素为0的矩阵。
在实际应用中,稀疏矩阵的存储和计算都会带来一定的困扰。
为了高效地存储和处理稀疏矩阵,我们可以使用十字链表法。
一、稀疏矩阵的特点稀疏矩阵的特点是其中绝大部分元素为0,而只有少部分非零元素。
这导致稀疏矩阵的存储空间浪费很大,因此需要采取一种有效的存储方式。
二、十字链表法的原理十字链表法是一种组合了链表和线性表的数据结构,用于存储稀疏矩阵。
具体实现如下:1. 定义两个链表headRow和headCol,分别用于存储行和列的头节点;2. 每个非零元素都对应一个结点,结点包含四个属性:行号row、列号col、值value以及指向下一个非零元素的指针nextRow和nextCol;3. headRow链表中的每个节点都指向同一行中的第一个非零元素,而headCol链表中的每个节点都指向同一列中的第一个非零元素;4. 非零元素之间通过nextRow和nextCol指针连接。
通过这种方式,我们可以高效地存储稀疏矩阵,并可以方便地进行矩阵的各种操作。
三、十字链表法的优势相比于其他存储稀疏矩阵的方法,十字链表法有以下几个优势:1. 空间利用率高:相比于使用二维数组存储,十字链表法可以大大减少存储空间的浪费,因为只存储非零元素及其位置信息;2. 支持高效的插入和删除操作:十字链表法可以通过调整指针的指向来进行插入和删除操作,而不需要像其他方法那样移动元素;3. 方便进行矩阵操作:通过十字链表法,我们可以方便地进行稀疏矩阵的各种操作,如矩阵相加、矩阵相乘等。
四、十字链表法的应用十字链表法广泛地应用于各个领域,特别是在图论和网络分析中。
在这些领域中,往往需要处理大规模的稀疏矩阵,而十字链表法能够有效地解决这个问题。
以社交网络为例,社交网络中的用户和用户之间往往存在着复杂的关系。
通过将社交网络建模成稀疏矩阵,可以使用十字链表法来存储和处理这些关系。
这样可以方便地进行各种网络分析操作,如查找某个用户的好友、计算两个用户之间的距离等。
十字链表和九宫格算法
十字链表和九宫格算法全文共四篇示例,供读者参考第一篇示例:十字链表和九宫格算法是两种经典的数据结构和算法,在计算机科学领域中具有重要的应用价值。
本文将介绍这两种算法的原理、特点及应用场景,以帮助读者更深入地理解它们。
首先,我们来看看十字链表算法。
十字链表是一种用于表示稀疏矩阵的数据结构,它能够高效地存储和检索稀疏矩阵中的非零元素。
在十字链表中,每个非零元素都会被封装成一个节点,并且节点之间通过指针相互连接,形成一个十字形的链表结构,从而方便对矩阵进行高效的操作。
十字链表算法的核心思想是将原本存储在二维数组中的稀疏矩阵转换成一个链表的形式,从而减少存储空间的消耗和提高检索效率。
通过使用指针连接的方式,可以方便地访问任意一个非零元素,并且在进行矩阵运算时能够大大提高运算效率。
十字链表算法在图论、线性代数和计算机图形学等领域都有广泛的应用。
比如在图论中,可以利用十字链表算法来存储图的邻接矩阵,并且通过遍历链表来查找图中的路径和环路。
在计算机图形学中,可以使用十字链表算法来表示图像的稀疏像素点,从而实现图像的压缩和处理。
接下来,我们来介绍一下九宫格算法。
九宫格算法是一种常用的数独解题算法,它通过递归和回溯的方式来解决数独难题,求解出数独题目的唯一解。
在数独游戏中,每个九宫格都由9个小格子组成,玩家需要填入1-9的数字,使得每一行、每一列和每个九宫格内的数字都不重复。
九宫格算法的核心思想是从数独题目的第一个空格开始逐个填入数字,然后检查当前数字是否符合数独规则。
如果符合规则,则填入下一个空格,依次递归进行。
如果填入的数字不符合规则,则回溯到上一个位置,重新填入其他数字,直到找到正确的解。
九宫格算法在解决数独难题和其他逻辑推理问题上有着重要的应用。
通过使用递归和回溯的方式,可以高效地求解出数独题目的解,并且在解决其他逻辑谜题时也能够发挥重要作用。
总的来说,十字链表算法和九宫格算法都是计算机科学中重要的数据结构和算法,它们在不同领域有着广泛的应用价值。
(原创)数据结构之十字链表总结
(原创)数据结构之⼗字链表总结7-1 稀疏矩阵(30 分)如果⼀个矩阵中,0元素占据了矩阵的⼤部分,那么这个矩阵称为“稀疏矩阵”。
对于稀疏矩阵,传统的⼆维数组存储⽅式,会使⽤⼤量的内存来存储0,从⽽浪费⼤量内存。
为此,可以⽤三元组的⽅式来存放⼀个稀疏矩阵。
对于⼀个给定的稀疏矩阵,设第r⾏、第c列值为v,且v不等于0,则这个值可以表⽰为 <r,v,c>。
这个表⽰⽅法就称为三元组。
那么,对于⼀个包含N个⾮零元素的稀疏矩阵,就可以⽤⼀个由N个三元组组成的表来存储了。
如:{<1, 1, 9>, <2, 3, 5>, <10, 20, 3>}就表⽰这样⼀个矩阵A:A[1,1]=9,A[2,3]=5,A[10,20]=3。
其余元素为0。
要求查找某个⾮零数据是否在稀疏矩阵中,如果存在则输出其所在的⾏列号,不存在则输出ERROR。
输⼊格式:共有N+2⾏输⼊:第⼀⾏是三个整数m, n, N(N<=500),分别表⽰稀疏矩阵的⾏数、列数和矩阵中⾮零元素的个数,数据之间⽤空格间隔; 随后N⾏,输⼊稀疏矩阵的⾮零元素所在的⾏、列号和⾮零元素的值;最后⼀⾏输⼊要查询的⾮0数据k。
输出格式:如果存在则输出其⾏列号,不存在则输出ERROR。
输⼊样例:在这⾥给出⼀组输⼊。
例如:10 29 32 18 -107 1 988 10 22输出样例:在这⾥给出相应的输出。
例如:8 10解题思路:实际上这道题⽤三元组写轻松解决,但是这⾥想讲的是⼗字链表;⼗字链表的图⼤致如下:那么如何去实现呢;看以下代码:因为下⾯都有注释,这⾥便不赘述了。
1 #include<iostream>2 #include<stdio.h>3using namespace std;45struct OLNod{6int i ; //该⾮零元的⾏下标;7int j ; //该⾮零元的列下标;8int value ; //该⾮零元的数值;9struct OLNod *right ,*down ;//该⾮零元所在的⾏表和列表的后继链域;10 };11struct CrossL{12 OLNod **rhead, **sead;13//⼗字链表的⾏头指针和列头指针;定义为指向指针的指针;14int row; //稀疏矩阵的⾏数;15int col; //稀疏矩阵的列数;16int num; //稀疏矩阵的⾮零个数;17 };1819int InitSMatrix(CrossL *M) //初始化M(CrossL)类型的变量必须初始化;20 {21 (*M).rhead = (*M).sead = NULL;22 (*M).row = (*M).col = (*M).num = 0;23return1;24 }2526int DestroysMatrix(CrossL *M) //销毁稀疏矩阵M;27 {28int i ;29 OLNod *p,*q;30for( i = 1 ; i <= (*M).row;i++)31 {32 p = *((*M).rhead+i); //p指针不断向右移;33while(p!=NULL)34 {35 q = p ;36 p = p ->right;37delete q; //删除q;38 }39 }40delete((*M).rhead); //释放⾏指针空间;41delete((*M).sead); //释放列指针空间;42 (*M).rhead = (*M).sead = NULL; //并将⾏、列头指针置为空;43 (*M).num = (*M).row = (*M).col = 0; //将⾮零元素,⾏数和列数置为0; 44return1;45 }46int CreatSMatrix(CrossL *M)47 {48int i , j , m , n , t;49int value;50 OLNod *p,*q;51if((*M).rhead!=NULL)52 DestroysMatrix(M);53 cin>>m>>n>>t; //输⼊稀疏矩阵的⾏数、列数和⾮零元个数;54 (*M).row = m;55 (*M).col = n ;56 (*M).num = t;57//初始化⾏链表头;58 (*M).rhead = new OLNod*[m+1];//为⾏头指针申请⼀个空间;59if(!(*M).rhead) //如果申请不成功,则退出程序;60 exit(0);61//初始化列链表头;62 (*M).sead = new OLNod*[n+1];//为列表头申请⼀个空间;63if(!(*M).sead) //如果申请不成功,则退出程序;64 exit(0);65for(int k = 1 ; k <= m ; k++)66 {67 (*M).rhead[k] = NULL;//初始化⾏头指针向量;各⾏链表为空链表;68 }69for(int k = 1 ; k <= n ;k++)70 {71 (*M).sead[k] = NULL;//初始化列头指针向量;各列链表为空链表;72 }73for(int k = 0 ; k < t ;k++) //输⼊⾮零元素的信息;74 {75 cin>>i>>j>>value;//输⼊⾮零元的⾏、列、数值;76 p = new OLNod();//为p指针申请⼀个空间;77if(!p) //e如果申请不成功;78 exit(0); //退出程序;79 p->i = i;80 p->j = j;81 p->value = value;82if((*M).rhead[i]==NULL) //如果⾏头指针指向的为空;83 {84//p插在该⾏的第⼀个结点处;85 p->right = (*M).rhead[i];86 (*M).rhead[i] = p;87 }else//如果不指向空88 {89for(q = (*M).rhead[i];q->right; q = q->right);90 p->right = q->right;91 q->right = p;9293 }94if((*M).sead[j]==NULL)//如果列头指针指向的为空;95 {96//p插在该⾏的第⼀个结点处;97 p->down = (*M).sead[j];98 (*M).sead[j] = p;99 }else//如果不指向空100 {101for(q = (*M).sead[j];q->down;q = q->down);102 p->down = q->down;103 q->down = p;104 }105 }106return1;107 }108int PrintSMatrix(CrossL *M)109 {110int flag = 0;111int val ;//要查找的元素的值;112 cin>>val; //输⼊要查找的s值;113 OLNod *p;114for(int i = 1 ; i <= (*M).row ;i++)115 {116for(p = (*M).rhead[i];p;p = p->right) //从⾏头指针开始找,不断向右找117 {118if(p->value==val) //如果能找到119 {120 cout<<p->i<<""<<p->j; //输出⾏下标和列下标121 flag = 1; //标记找到该元素;122 }123 }124 }125126127if(flag==0) //如果找不到128 {129 cout<<"ERROR\n";130 }131132 }133int main()134 {135 CrossL A; //定义⼀个⼗字链表;136 InitSMatrix(&A); //初始化;137 CreatSMatrix(&A); //创建;138 PrintSMatrix(&A); //输出;139 DestroysMatrix(&A); //销毁;140return0;141 }。
数据结构 课程设计 十字链表
数据结构课程设计十字链表xx学院一、问题的分析和任务定义:该设计是采用十字链表表示稀疏矩阵,并实现矩阵的加法运算。
还要检查有关运算的条件,并对错误的条件产生报警。
根据对该程序任务的理解,对本程序分别从以下几个方面进行分析: 1.输入数据的的类型和输入的范围该程序首先输入稀疏矩阵的行数和列数,再输入一个有非零元素的行号,有非零元素的列号,再输入非零元素的值,然后输入当前行下一个元素所在的列,如果该行只有一个非零元素就直接输入-1结束当前行的一组数据,如果还有其他的非零元素的话就输入当前行下一个非零元素所在的列,就这样,直到该当前行的非零元素输入完。
然后再输入当前列下一个非零元素的所在的行,其步骤与前一步相同。
其输入值都为稀疏矩阵的数据,类型都为整型。
2.输出数据的形式这样得到一个稀疏矩阵a,以同样的方法就可以得到另一个稀疏矩阵b,最后就可以得到稀疏矩阵a和稀疏矩阵b的和矩阵.输出是以稀疏矩阵的标准形式输出的。
输出值的有两种:一种是字符,一种是整数。
输出的字符型数据是稀疏矩阵的代号,输出的整型数据为稀疏矩阵的值。
3.测试数据测试数据一:测试数据二:稀疏矩阵的行数与列数:3 3 稀疏矩阵的行数与列数:3 3 矩阵a:矩阵b:矩阵a:矩阵b: 2 0 0 0 0 2 2 0 0 0 0 00 0 6 3 0 0 0 0 0 0 0 07 0 0 2 0 5 0 0 0 7 0 0二、概要设计和数据结构的选择:1.算法(程序)中用到的所有各种数据类型的定义:定义整型数据为int m,int n,分别代表矩阵的行和列;定义十字链表类型结点OLnode *h,*p分别代表为头结点开辟空间和指向下一结点;在主函数中定义OLnode *a,*b,分别表示a,b两个稀疏矩阵。
2.各程序模块之间的层次关系:程序中用到的函数:1 OLnode *create(int m,int n); 创建以十字链表表示的一个元素全为零的稀疏矩阵。
稀疏矩阵的十字链表存储的思路
稀疏矩阵的十字链表存储的思路
稀疏矩阵是指大部分元素都是零的矩阵。
为了避免浪费存储空间,可以采用十字链表存储法。
具体实现思路如下:
1. 定义结构体Node,表示矩阵中的一个非零元素。
2. 定义结构体CrossListNode,表示十字链表中的一个节点,
包含4个指针,分别指向同一行中的下一个非零元素、同一列中的下一个非零元素、上一个非零元素以及左一个非零元素。
3. 定义结构体CrossListMatrix,表示十字链表矩阵,包含三
个变量:矩阵的行数、列数和非零元素数目,以及两个指针,分别指向行和列的头节点。
4. 创建行和列的头节点,依次扫描矩阵中的非零元素,创建一
个Node节点,并把它插入到行和列的链表中。
同时,记录该元素在
行和列中的位置,以便于更新节点的指针。
5. 最后建立行和列之间的链接,即将同一行中的节点按照列的
顺序链接起来,同理,将同一列中的节点按照行的顺序链接起来。
6. 完成十字链表矩阵的存储。
通过以上方法,可以有效地减少存储空间的浪费,提高矩阵的存储效率,同时也方便了对矩阵中非零元素的操作。
- 1 -。
自主实验6系数矩阵十字链表的存储
电子信息学院实验报告书课程名:数据结构题目:系数矩阵十字链表的存储实验类别设计班级:BX1002学号:101003020211姓名:沈雅婷2011年10月30日1、实验目的(1) 掌握稀疏矩阵十字链表存储的方法。
(2) 掌握稀疏矩阵的显示、查找等基本算法。
2、实验内容(1) 创建空的稀疏矩阵的十字链表存储结构。
(2) 稀疏矩阵十字链表的数据输入。
(3) 稀疏矩阵十字链表的数据显示。
(4) 稀疏矩阵十字链表的数据查找。
3、实验要求(1) 利用C (C++)语言完成算法设计和程序设计。
(2) 上机调试通过实验程序。
(3) 输入右侧矩阵A ,检验程序运行结果。
(4) 给出具体的算法分析,包括时间复杂度和空间复杂度等。
(5) 撰写实验报告。
A=⎪⎪⎪⎪⎪⎪⎪⎭⎫⎝⎛8-0000000000201-007003 4、实验(1) 实验步骤 1、建立结构体。
2、编写调用函数。
3、运行程序,并且抓图粘图。
4、撰写实验报告。
(2) 源程序#include<iostream.h>#include<stdio.h>#include<iomanip.h>#include<stdlib.h>struct linknodeint rows,cols;linknode *down,*right;union vnext{int v;linknode *next;}node;};linknode *CreateMatlind();linknode *InputMatlind(linknode,int);void ShowMatlind(linknode);void SearchMatlind(linknode *hm,int s);linknode *CreateMatlind() // 创建空十字链表{int i,j,maxlin;linknode *hm,*cp[100],*p;printf("\n\t\t请输入稀疏矩阵的行数,列数(用逗号隔开): ");scanf("%d,%d",&i,&j);if (i>j)maxlin=i;elsemaxlin=j;hm=new linknode;cp[0]=hm;for (int l=1;l<=maxlin;l++){p=new linknode;p->rows=0;p->cols=0;p->down=p;p->right=p;cp[l]=p;cp[l-1]->node.next=p;}cp[maxlin]->node.next=hm;hm=new linknode;hm->rows=i;hm->cols=j;return hm;}linknode *InputMatlind(linknode *hm,int s) // 输入非零元素{linknode *cp[100],*p,*q;int m,n,t;int i,j,k,maxlin;i=hm->rows;j=hm->cols;if (i>j)maxlin=i;elsemaxlin=j;cp[0]=hm;for (int l=1;l<=maxlin;l++){p=new linknode;p->rows=0;p->cols=0;p->down=p;p->right=p;cp[l]=p;cp[l-1]->node.next=p;}cp[maxlin]->node.next=hm;for (int x=0;x<s;x++){printf("\n\t\t请输入非零元的行号,列号和值(用逗号隔开): ");scanf("%d,%d,%d",&m,&n,&t);p=new linknode;p->rows=m;p->cols=n;p->node.v=t;k=1;q=cp[m];while (k){if ((q->right==cp[m]) || (q->right->cols>n)){p->right=q->right;q->right=p;k=0;}else if(q->right->cols==n){p->right=q->right->right;q->right=p;k=0;}else if(q->right->cols<n){q=q->right;k=1;}}k=1;q=cp[n];while (k){if ((q->down==cp[n]) || (q->down->rows>m)) {p->down=q->down;q->down=p;k=0;}else if (q->down->rows==m){p->down=q->down->down;q->down=p;k=0;}else if (q->down->rows<m){q=q->down;k=1;}}}return hm;}void ShowMatlind(linknode *hm) // 显示十字链表{int m,n;linknode *p,*q;m=hm->rows;n=hm->cols;q=p=hm->node.next;p=p->right;cout<<endl<<endl;printf("\n\t\t");for (int i=1;i<=m;i++){for (int j=1;j<=n;j++){if ((p->rows==i) && (p->cols==j)){printf("%8d",p->node.v);}elseprintf("%8c",'0');if ((j==n) && (p->right==q))break;else if (p->right!=q)p=p->right;}printf("\n\n\t\t");p=q;q=p=p->node.next;p=p->right;}}void SearchMatlind(linknode *hm,int s) // 查找元素{int m,n,k;linknode *p,*q;m=hm->rows;n=hm->cols;q=p=hm->node.next;p=p->right;k=1;while(k){if ((p->node.v)==s){printf("\n\t\t 行列值\n");printf("\n\t\t元素位置:%2d %2d %2d\n",p->rows,p->cols,p->node.v);k=0;}else if (p->right!=q)p=p->right;else{p=q;q=p=p->node.next;if (p==hm){printf("\n\t\t十字链表中无此元素! \n");k=0;}p=p->right;}}}void main(){int s,k,ch=1;int choice;linknode *hm=NULL;while (ch){printf("\n");printf("\n\t\t 稀疏矩阵的十字链表存储系统\n");printf("\n\t\t********************************************");printf("\n\t\t* 1-----新建十字链表*");printf("\n\t\t* 2-----显示十字链表*");printf("\n\t\t* 3-----查找元素*");printf("\n\t\t* 0-----退出*");printf("\n\t\t********************************************");printf("\n\n\t\t 请输入菜单号: ");scanf("%d",&choice);switch(choice){case 1:hm=CreateMatlind(); // 调用创建空十字链表函数do{printf("\n\t\t请输入稀疏矩阵的元素个数: ");scanf("%d",&s);if (s>((hm->rows)*(hm->cols))){printf("\n\t\t元素个数超标! 应小于%d个\n",hm->rows*hm->cols);k=1;}elsek=0;}while (k);hm=InputMatlind(hm,s); // 调用输入非零元素函数break;case 2:if (hm==NULL){printf("\n\t\t链表为空! \n");break;}else{ShowMatlind(hm);break;}case 3:if (hm==NULL){printf("\n\t\t链表为空! \n");break;}else{printf("\n\t\t请输入您要查找的元素: ");scanf("%d",&s);SearchMatlind(hm,s); // 调用查找非零元素函数break;}case 0:ch=0;break;}if (choice==1 || choice==2 || choice==3){printf("\n\t\t");system("pause");system("cls");}}}4、测试数据与实验结果(可以抓图粘贴)5、结果分析与实验体会。
稀疏矩阵的十字链表存储结构
稀疏矩阵的十字链表存储结构
稀疏矩阵是指矩阵中绝大多数元素为0,而仅有少数元素非0,这种矩阵的存在会占用大量的存储空间,而且在进行一些操作时也会变得非常低效。
为了解决这个问题,可以采用十字链表的方式对稀疏矩阵进行存储。
十字链表存储结构是一种非常高效的稀疏矩阵存储方法。
它将矩阵中所有非零元素按行列坐标分别存储到两个链表中,并且在每个节点中还包含指向该元素左右上下四个方向节点的指针,形成一个类似于十字路口的结构。
这样一来,我们就可以在O(n)的时间内轻松地遍历矩阵中所有的非零元素,而且还能够快速地定位和更新某个元素的值,大大提高了存储和处理的效率。
在十字链表存储结构中,我们通常会使用头节点来记录矩阵的大小和非零元素的总数,以及行列链表的头指针。
节点中的数据需要同时包含行列坐标和元素的值,这样才能够快速地进行查找和替换。
同时,在插入或删除一个元素时,我们需要更新该元素所在节点的邻接节点的指针,以保证整个结构的完整性和正确性。
总的来说,十字链表存储结构是一种非常高效和灵活的稀疏矩阵存储方案,可以大大减小矩阵的存储空间和处理时间,同时也可以满足各种复杂的操作需求。
在实际应用中,我们可以根据具体的问题和数据特征灵活地选择适合的数据结构和算法,来达到更好的效果和效率。
实验6:稀疏矩阵十字链表的存储讲课稿
cp[l-1]->node.n ext=p;
}
cp[maxli n]->node.n ext=hm;
for (int x=0;x<s;x++)
{
printf("\n\t\t请输入非零元的行号,列号和值(用逗号隔开):");
sca nf("%d,%d,%d",&m,&n,&t);
p=new linkno de;
if (i>j)
maxli n=i;
else
maxli n=j;
cp[0]=hm;
for (i nt l=1;l<=maxli n;l++)
{
p=new linkno de;
p->rows=0;
仅供学习与交流,如有侵权请联系网站删除谢谢3
p->cols=0;
p->dow n=p;
p->right=p;
实 验6: 稀 疏 矩 阵 十
字链表的存储
电子信息学院
实验报告书
课程名:数据结构
题目:稀疏矩阵十字链表的存储实验类别设计
班级:BX1001
学号:24
姓名:肖望龙
2011年10月23日
仅供学习与交流,如有侵权请联系网站删除谢谢2
1实验题目
(1)掌握稀疏矩阵十字链表存储的方法。
(2)掌握稀疏矩阵的显示、查找等基本方法。
2、实验内容
(1)创建空的稀疏矩阵的十字链表存储结构。
(2)稀疏矩阵十字链表的数据输入。
(3)稀疏矩阵十字链表的数据显示。
(4)稀疏矩阵十字链表的数据查找。
表示稀疏矩阵的十字链表
void invert(node *head)
{ node *p,*q,*r;
例
p=head;
q=p->next;
3
while(q!=NULL) /*没有后继时停止*/
.
{
1
r=q->next; q->next=p;
算
p=q;
法
q=r;
}
head->next=NULL;
head=p;
}
链表
例3.2
}
链表
例3.3
给出在双链表中第i个结点(i≥0)之后插入一个元素为x的 结点的函数。
解:在前面双链表一节中,已经给出了在一个结点之前 插入一个新结点的方法,在一个结点之后插入一个新结 点的思想与前面是一样的。
链表
void insert(dnode *head,int i,x)
{
dnode *s,*p;
link(node *head1,head2)
{
例
node *p,*q; p=head1;
3.
while(p->next!=head1)
2
p=p->next;
算
q=head2; while(q->next!=head2)
法
q=q->next;
p->next=head2;
q->next=head1;
对于每行、每列的循环链表都有一个空表 头结点,以利于元素的插入和删除运算。 这些空表头结点的行号、列号都标成零, 以便和其它结点相区别。
整个十字链表有一个总的空表头结点,在 一般结点标以行号、列号之处,此结点是 标出矩阵的行数m和列数n。
采用十字链表存储的稀疏矩阵
采⽤⼗字链表存储的稀疏矩阵Description当矩阵的⾮零元个数和位置在操作过程中变化较⼤时,就不宜采⽤顺序存储的结构来表⽰三元组的线性表了。
因此,在这种情况下,采⽤链式存储结构表⽰三元组更为恰当。
⼗字链表就是能够实现这样功能的⼀种数据结构。
在⼗字链表中,每个⾮零元可以⽤⼀个包含5个域的结点表⽰。
其中i、j和e这3个域分别表⽰该⾮零元所在的⾏、列和⾮零元的值,向右域right⽤来链接同⼀⾏中下⼀个⾮零元,⽽向下域down⽤来链接同⼀列中下⼀个⾮零元。
同⼀⾏的⾮零元通过right域链接成⼀个线性链表,同⼀列的⾮零元通过down域链接成⼀个线性链表。
每个⾮零元既是某个⾏链表中的⼀个结点,⼜是某个列链表中的⼀个结点,整个矩阵通过这样的结构形成了⼀个⼗字交叉的链表。
稀疏矩阵的⼗字链表类型可以描述如下:下⾯是建⽴稀疏矩阵⼗字链表的算法描述:给出⼀个稀疏矩阵,请将其存储到⼀个⼗字链表中,并将存储完毕的矩阵输出。
Input输⼊的第⼀⾏是两个整数r和c(r<200, c<200, r*c <= 12500),分别表⽰⼀个包含很多0的稀疏矩阵的⾏数和列数。
接下来有r⾏,每⾏有c个整数,⽤空格隔开,表⽰稀疏矩阵的各个元素。
Output输出读⼊的矩阵。
输出共有r⾏,每⾏有c个整数,每个整数后输出⼀个空格。
请注意⾏尾输出换⾏。
Sample Input5 60 18 0 0 0 00 0 67 0 0 00 0 0 0 0 410 0 47 62 0 00 0 0 0 0 35Sample Output0 18 0 0 0 00 0 67 0 0 00 0 0 0 0 410 0 47 62 0 00 0 0 0 0 35HINT提⽰:对于m⾏n列且有t个⾮零元的稀疏矩阵,算法5.4的执⾏时间为O(t×s),其中s=max(m,n)。
这是由于每建⽴⼀个⾮零元结点时,都需要通过遍历查询它所在的⾏表和列表中的插⼊位置。
I第九讲(十字链表及基本操作)
(b)每行 列设一个表头结点(结构同元素结点), 每行/列设一个表头结点 结构同元素结点), 每行 列设一个表头结点( 为链构成循环链表, 以down/right为链构成循环链表,即第 列头结点的 为链构成循环链表 即第i列头结点的 down指向该列上第 个非 元素,第i 行头结点的 指向该列上第1个非 元素, 指向该列上第 个非0元素 right指向该行第 个非 元素.第i列/行上最后一个 指向该行第1个非 元素. 列 行上最后一个 指向该行第 个非0元素 结点的down/right指向该列 行的头结点.若某列 行 指向该列/行的头结点 若某列/行 结点的 指向该列 行的头结点. 中无非0元素 则令它的头结点down/right域指向自 元素, 中无非 元素,则令它的头结点 域指向自 己. (c)设一个总头结点(结构同元素结点),令总 设一个总头结点( ),令总 设一个总头结点 结构同元素结点), 头结点和各个列/行头结点用 字段 按列/行序构 头结点和各个列 行头结点用val字段,按列 行序构 行头结点用 字段, 成一个循环单链表. 成一个循环单链表.
row元素在稀疏矩阵中的行号col元素在稀疏矩阵中的列号val元素值down指向同列中下一个非0元素结点right指向同行中下一个非0元素结点rowcolvaldownrightb每行列设一个表头结点结构同元素结点以downri上第1个非0元素第i行头结点的right指向该行第1个非0元素
(d)可令总头结点的 可令总头结点的row,col与val 分别表示矩阵的 , 与 可令总头结点的 最大行号,列号与非0元素个数 元素个数, 最大行号,列号与非 元素个数,而down/right指向 指向 行的头结点. 第1列/行的头结点.该总头结点可作为整个十字链表 列 行的头结点 的代表. 的代表. (e)由于行与列的头结点分别使用 由于行与列的头结点分别使用right域与 域与down域 由于行与列的头结点分别使用 域与 域 (不同时使用 ,故第i列与第 行头结点可合用同一个 不同时使用),故第 列与第i 不同时使用 列与第 头结点(对所有可能的i),以节省存储空间. ),以节省存储空间 头结点(对所有可能的i),以节省存储空间. (f)有时,为了快速访问行 列头结点,设置一个一维 有时, 列头结点, 有时 为了快速访问行/列头结点 数组headNodes[] ,使headNodes[i]指向 行/列的 数组 指向i行 列的 指向 头结点.但这并不是必须的,因为各行/列的头结点 头结点.但这并不是必须的,因为各行 列的头结点 已形成了一个循环单链表, 已形成了一个循环单链表,故若已知十字链表总头 结点,即可搜索到任一头结点. 结点,即可搜索到任一头结点.
稀疏矩阵十字链表的存储
printf("\n\t\t* 2-----显示十字链表 *");
printf("\n\t\t* 3-----查 找 元 素 *");
printf("\n\t\t* 0-----退 出 *");
printf("\n\t\t********************************************");
电子信息学院
实验报告书
课程名:数据结构
题 目:稀疏矩阵十字链表的存储
实验类别:设计
班 级:BX1001
学 号:41
姓 名:赵艳
2011年10月24日
1、实验题目
(1)掌握稀疏矩阵十字链表存储的方法。
(2)掌握稀疏矩阵的显示,查找等基本算法。
2、实验内容
(1)创建空的稀疏矩阵十字链表存储结构。
(2)稀疏矩阵十字链表的数据输入。
printf("\n\t\t请输入稀疏矩阵的行数,列数(用逗号隔开): ");
scanf("%d,%d",&i,&j);
if (i>j)
maxlin=i;
else
maxlin=j;
hm=new linknode;
cp[0]=hm;
for (int l=1;l<=maxlin;l++)
{
p=new linknode;
p=new linknode;
p->rows=m;
p->cols=n;
p->=t;
k=1;
稀疏矩阵的十字链表存储的思路
稀疏矩阵的十字链表存储的思路
稀疏矩阵是一种大多数元素都为0的矩阵,而十字链表是一种常
见的数据结构,用于存储稀疏矩阵。
十字链表提供了一种有效的方法,可以对矩阵进行高效的访问和操作。
十字链表的存储方式是将矩阵分成两个链表:行链表和列链表。
行链表和列链表中的每个节点都存储了一个非零元素和该元素的行编
号和列编号。
同时,每个节点也包含了指向下一个相同行或相同列的
节点的指针。
在十字链表中,每个节点都可以快速找到它所处的行和列以及与
它相邻的元素。
这使得我们可以在矩阵中进行诸如插入、删除、修改
及查找等操作。
在操作过程中,我们可以通过指针操作找到相邻的非
零元素,从而充分利用稀疏矩阵的特殊性质。
对于一个稀疏矩阵,我们需要将每一个非零元素存储到十字链表中。
首先,我们需要创建一个新的节点,并为它分配内存空间。
然后,我们需要将该节点插入到正确的位置,即行链表和列链表中。
插入操作的基本思路是,我们首先遍历行链表,找到该元素所在
的行号。
然后在该行号的节点中,按照列号的大小插入该新节点。
同时,我们需要在列链表中找到该元素所在的列号,并在该列号的节点
中插入新节点。
除了插入操作外,十字链表还支持删除操作、修改操作和查找操作。
这些操作都可以通过指针操作实现。
总的来说,十字链表是一种高效的数据结构,可以有效地存储稀
疏矩阵。
通过使用十字链表,我们可以对矩阵进行各种操作,而不必
费力遍历整个矩阵。
在实现稀疏矩阵算法时,我们常常会使用十字链
表这种数据结构。
2014通化事业单位通用知识:十字链表的存储结构
2014通化事业单位通用知识:十字链表的存储结构更多信息,欢迎关注:吉林事业单位招聘考试网(/jilin/)
【导语】在事业单位考试中,计算机专业知识的复习向来是考生复习备考阶段的一大重点,其中中公事业单位考试网为计算机基础知识的复习为考生提供知识点梳理,帮助考生备考!
十字链表的存储结构
#define MAXR 100
#define MAZC 100
typdef struct olnode
{int row, col;
ELEMTP Val;
struct olnode *down, *right;
}OLNode;
typedef struct Cist
{OLNode *rhead[MAXR+1],*chead[MAXC+1];
INT mu,nu,tu;
}Crosslist;
以上是中公事业单位考试网为考生梳理计算机基础知识点,供大家学习识记!。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
是 : 利 用 十字 链 表 动态 分 配 内存 的优 点 , 免 以 ① 避 往 使 用 静 态 数 组 存 储 计 算 所 带 来 的 内存 的浪 费 ;
② 十字 链 表适 合 存 储 矩 阵 元 素 , 有 2个 节 点 域 它 和 2个 指 针 域 , 点 域 分 别 存 放 矩 阵 的行 号 、 节 列 号 , 针 域 分 别 指 向本 行 、 列 的下 一 个 元 素 , 指 本 这 样 可 以将 同行 ( ) 素 串联 在 同 一链 表 之 中 。同 列 元 时 当 网络 结 构 改 变 时 , 能 够快 速 实 现 导 纳 矩 阵 它
文 章 编 号 :1 0 — 7 9 2 O ) 3 0 8 — 3 0 0 7 0 ( O 2 0 — 0 3 0
用 十 字 链 表 实 现 导 纳 矩 阵 的 存 储
赵 强 董朝霞
( 中 科 技 大 学 水 电 及 数 字 化 工 程 学 院 ,湖 北 武 汉 4 0 7 ) 华 3 0 4
导 纳 矩 阵 建 立 和 修 改
2 1 导 纳 矩 阵 的 建 立 .
1 十 字 链 表 简 介
十字链 表 是 有 向图 的一 种链 式 存 储 结 构 。若
将 有 向图 的邻 接矩 阵看 成 是 稀 疏 矩 阵 的话 , 十 则
在 编 制 生 成 导 纳矩 阵 的 程 序 中 , 虑 到 导 纳 考 矩 阵 的特 点 , 十字 链 表进 行 了 简化 : 对 a .由于 导 纳 矩 阵是 一 个 稀 疏 的对 称 矩 阵 , 故 仅 仅 保存 导 纳矩 阵 的 上 三 角 部 分 , 以对 于所 有 所 的节 点 , 行号 小 于 或 等 于 列号 ( 当节 点 还有 接 地 支 路 时 , 遵 守 该 规 则 , 定 其 行 号 域 ( v re ) 不 约 i etx 存 放 i列 号 存 放零 , if , 其 no域 存 放 该 接地 支 路 的
无 法 预 知 电力 系统 中 网络 节 点 的规 模 , 只 能 开 故
辟 出足 够 大 的数组 , 而 造成 内存 的浪 费 。 文 提 从 本 出 用 十字 链 表 实现 导 纳 矩 阵 的存 储 , 主要 思 想 其
图 1 十 字 链 录 结 构
以对 角 元 素 为 每 行 、 列 的 头节 点 , i ik 每 其 n l 指 针 和 j ik指针 分 别 指 向本 行 、 列 的某 一 个 n l 本 非零 非对 角 元 素 , 样 , 这 每行 所 有 的非 零元 素链 接
维普资讯
第 20 第 3 卷 期 2 002年 9月
水
电
能
源
科
学
V o1 20 N O. . 3 Se .2 0 0 2 pt
I t r a i n lJ u n lHYDROELECTRI n e n to a o r a C ENERGY
元素 的节点 ; f i o存放 该 元 素 的相 关 信息 ; n 当行 号 和 列号 相 同时 , e t 指 向下 一 个行 号 和列 号 相 nx 域
同 的节 点 , 即对 角元 素 用 n x 指 针链 接 在 同 一个 et 链 表 中 , 则 ,e t 为 ห้องสมุดไป่ตู้UI 。 否 nx 域 L[
导 纳 )。
字链 表 也 可 以 看成 是 邻 接 矩 阵 的链 表 存 储 结 构 ,
用来 存 储 稀 疏矩 阵 。 十字链 表 中 , 在 每个 元 素都 是
一
个节 点 , 图 1 示 的结 构 来表 示 , 由 6 域 用 所 它 个
组 成 。 中节 点域 i e tx和 j e tx为该 元素 的 其 re v r v e 行 号 和列 号 ; l k指针 域 指 向 同一 行 中下 一个 非 ii n 零元 素 的节 点 ,l k指 针 域指 向 同一 列 中下 一 个 ji n
收 稿 日期 :2 0 — 1 1 0 11— 3
b .导 纳 矩 阵 中 的对 角元 素 从 小 到 大 按 序 排
作 者 简 介 :赵 强 ( 7)男 ( 族 ) 湖 南 湘 潭 人 , 中 科 技 大 学 硕 士 研 究 生 。 17一, 汉 9 , 华
摘 要 : 出在 电力 系 统 潮 流 计 算 中 采 用 十 字链 表 实现 导 纳 矩 阵动 态 存 储 的 方 法 , 效 地 克 服 了利 用 静 态数 组 提 有 存 储 所 带 来 的 浪 费 内存 的缺 点 。 同 时 a 网 络 结 构 改 变时 , 用导 纳 矩 阵 的 动 态 存 储 结 构 能 够 快 速 地 实现 导 纳 3 _ - 使
矩 阵 的修 改 , 而 减 少 整 个 潮 流 计 算 的 时 间 。 从
关 键 词 :十 字 链 表 ;导 纳 矩 阵 ;电 力 系统 ;潮 流 计 算
中 图分 类 号 : TM 7 4 4 文 献 标 识 码 :A
导纳 矩 阵是 一 个 稀 疏 矩 阵 , 只需 要 存 储 导 纳 矩 阵 的非 零 元 素 , 即对 角元 素 和 非零 非 对 角元 素 。 在 导纳 矩 阵 中 , 角元 素 的个 数 等 于计 算 节 点 的 对 个数 , 每行 非零 非 对 角元 素 的个 数 等 于该 计 算节 点不 接 地 的支 路数 。通常 使 用静 态 数 组存 储 导 纳 矩 阵 的 对 角 元 素 和 非零 非 对 角 元 素 [ , 于 程 序 1 由 ]
的修 改 。
在 一 个 相 同 的 链 表 中 。再 定 义 一 个 总 头 节 点 n d — e d指 向第 一 个 对 角元 素 , 过 总 头节 点 , oeha 通 再经 过 对 角元 素 节 点 的 i ik和 j ik指 针 , n l n l 即可
访 问到所 有 的节 点 。