稀疏矩阵的十字链表创建与打印

合集下载

拓展阅读4——稀疏矩阵的十字链表

拓展阅读4——稀疏矩阵的十字链表

q->down=pa->down;
free (pa);
pa=qa;
} /*if (x==0)*/
else /*第一种情况*/
{
pa->v_next.v=x;
qa=pa;
}
pa=pa->right;
pb=pb->right; } } /*while*/ ca=ca->v_next.next; cb=cb->v_next.next; } while (ca->row==0) return Ha; }
hd[0]=H;
for(i=1; i<=s; i++)
{
p=(MNode*)malloc(sizeof(MNode));
/*申请第 i 个头结点*/
p->row=0; p->col=0;
p->right=p; p->down=p;
hd[i]=p;
hd[i-1]->v_next.next=p;
}
hd[s]->v_next.next=H;
q=hd[i];
while (q->right!=hd[i] && (q->right->col)<j )
/*按列号找位置*/
q=q->right;
p->right=q->right;
/*插入*/
q->right=p;
/*以下是将*p 插入到第 j 列链表中去,且按行号有序*/
q=hd[j];
while (q->down!=hd[j] && (q->down->row)<i ) q=q->down;

408考稀疏矩阵十字链表

408考稀疏矩阵十字链表

408考稀疏矩阵十字链表稀疏矩阵是指矩阵中绝大部分元素为0的情况下,只存储非零元素及其位置信息的一种存储方式。

在计算机科学中,稀疏矩阵的存储方式有多种,其中一种较为常见的方式是使用十字链表。

十字链表是一种基于链表的数据结构,用于表示稀疏矩阵。

它通过两个链表和一个头节点来表示稀疏矩阵的行和列。

具体来说,十字链表由以下几个部分组成:1. 头节点:头节点用于存储稀疏矩阵的行数、列数和非零元素的个数等基本信息。

2. 行链表:行链表由多个节点组成,每个节点代表稀疏矩阵的一行。

每个节点包含三个属性:行号、列号和值。

行链表按照行号从小到大的顺序排列。

3. 列链表:列链表由多个节点组成,每个节点代表稀疏矩阵的一列。

每个节点包含三个属性:行号、列号和值。

列链表按照列号从小到大的顺序排列。

4. 节点链接:行链表和列链表中的节点通过行号和列号进行链接。

对于每个节点,除了存储自身的行号、列号和值外,还需存储其所在行的下一个节点和所在列的下一个节点。

使用十字链表来存储稀疏矩阵的好处是可以大大减少存储空间的使用,尤其适用于稀疏矩阵中非零元素的个数相对较少的情况。

通过十字链表,我们可以快速访问稀疏矩阵中的非零元素,并且可以方便地进行行和列的插入、删除和修改操作。

下面举一个具体的例子来说明408考稀疏矩阵十字链表的应用。

假设有一个3行4列的稀疏矩阵,其中非零元素分别为6、8、9、7,它们的位置分别是(1, 2)、(2, 1)、(2, 3)、(3, 4)。

我们可以使用十字链表来表示这个稀疏矩阵。

我们创建一个头节点,存储稀疏矩阵的行数、列数和非零元素的个数,即3、4和4。

然后,我们创建4个节点,分别表示这4个非零元素。

这些节点的属性分别为:(1, 2, 6)、(2, 1, 8)、(2, 3, 9)和(3, 4, 7)。

同时,我们需要将这些节点链接到行链表和列链表中相应的位置。

在行链表中,我们将这些节点按照行号从小到大的顺序插入。

首先,我们插入节点(1, 2, 6),因为它的行号最小。

稀疏矩阵的十字链表存储

稀疏矩阵的十字链表存储

稀疏矩阵的⼗字链表存储稀疏矩阵的压缩存储有⼏种⽅式,如:三元组顺序表、⾏逻辑链接的顺序表和⼗字链表。

使⽤链表存储的好处是:便于矩阵中元素的插⼊和删除。

例如:“将矩阵B加到矩阵A上”,那么矩阵A存储的元素就会有变动。

⽐如会增加⼀些⾮零元,或者删除⼀些元素(因为b ij+a ij=0)。

下图是矩阵M和M的⼗字链表存储:⼗字链表及其结点可⽤如下结构体表⽰:typedef struct OLNode{int i, j; // ⾮零元的⾏列下标ElemType e;struct OLNode *right, *down; // 向右域和向下域} OLNode, *OLink;typedef struct{OLink *rhead, *chead; // ⾏链表和列链表的头指针数组int mu, nu, tu; // 稀疏矩阵的⾏数、列数和⾮零元个数} CrossList;在通过代码创建⼗字链表时,要特别注意right、down和rhead、chead这些指针的赋值。

现在来看“将矩阵B加到矩阵A上”这个问题。

所要做的操作:a ij +b ij,其结果⼀共会有4种情况:1. a ij(b ij = 0)(不做变化)2. b ij(a ij = 0)(在A中插⼊⼀个新结点)3. a ij +b ij ≠ 0 (改变结点a ij的值域)4. a ij +b ij = 0 (删除结点a ij)假设指针pa和pb分别指向矩阵A和B中⾏值相同的两个结点,对于上述4种情况的处理过程为:1. 若“pa == NULL”或“pa->j⼤于pb->j”,则在矩阵A中插⼊⼀个值为b ij的结点。

并且需要修改同⼀⾏前⼀结点的right指针,和同⼀列前⼀结点的down指针。

2. 若“pa->j⼩于pb-j”,则pa指针右移⼀步。

3. 若“pa->j等于pb-j”,并且“pa->e + pb->e != 0”,则修改pa->e即可。

数据结构 耿国华 西北大学 5-5稀疏矩阵的十字链表法

数据结构 耿国华 西北大学 5-5稀疏矩阵的十字链表法
第 5 章 数组和广义表 特殊矩阵--稀疏矩阵 十字链表法
1
第 5 章 数组和广义表
5.3 特殊矩阵的压缩存储
③稀疏矩阵:三元组顺序表 数据类型定义
#define MAXSIZE 1000 typedef struct {
int row, col; ElementType e ; }Triple;
③稀疏矩阵:十字链表的存储表示
一个结点除了数据域(i,j,elem)之外,还应该用两 个方向的指针(right, down),分别指向行和列。
right:用于链接同一行中的下一个元素; down:用于链接同一列中的下一个元素。
row col value down right
整个矩阵构成了一个十字交叉的链表,因此称十字链表。 每一行和每一列的头指针,用两个一维指针数组来存放。 3
/* 行号和列号 */ /* 元素值 */
typedef struct
{ Triple data[MAXSIZE +1]; /* data[0]未用 */ int m, n, len; /* 矩阵的行数、列数和非零元个数 */ 2
}TSMatrix;
第 5 章 数组和广义表
5.3 特殊矩阵的压缩存储Βιβλιοθήκη typedef struct
{
OLink *row_head,*col_head;
int m,n,len;
4
}CrossList;
第 5 章 数组和广义表 5.3 特殊矩阵的压缩存储
row col value down right
③稀疏矩阵 十字链表的举例 :
-3 0 0 -5
M= 0 -1 0 0 8 00 7
第 5 章 数组和广义表 5.3 特殊矩阵的压缩存储

数据结构 课程设计 十字链表

数据结构 课程设计 十字链表

数据结构课程设计十字链表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、功能要求:根据用户输入的矩阵,实现稀疏矩阵的求和运算,并输出结果。

2、输入要求:矩阵的数据在程序运行的时候由用户提供,先由用户输入稀疏矩阵的行数、列数和非零元个数。

再根据非零元个数,输入这些非零元,还需要用户为这些非零元输入行、列和非零元的值。

这样,一个稀疏矩阵就输入完成。

若输入4 3 2则表示这个稀疏矩阵有4行3列2个非零元然后用户需要为这两个非零元输入行、列、非零元的值如:1 2 24 1 1表示第一个非零元行为1,列为2,,值为2;第二个非零元行为4,列为1,值为1。

此过程输入的稀疏矩阵为:0 2 00 0 00 0 01 0 03、输出要求:输出按矩阵输出,按行列依次输出,非零元则输出非零元的值,不是非零元则输出“0”。

各元素之间用空格隔开。

最后输出完整的矩阵。

二、概要设计1.稀疏矩阵的抽象数据类型定义如下:ADT SparseMatrix {数据对象: D={a ij|i=1,2,3……m,j=1,2,3……n;a ij属于ElemSet,m和n分别是稀疏矩阵的行数和列数}数据关系: R={ Row, Col }Row={<a ij,a ij+1>|1<=i<=m,1<=j<=n-1}Col={<a ij,a i+1j>|1<=i<=m-1,1<=j<=n}基本操作:CreateSMatrix(&M);//建立稀疏矩阵MDestroySMatrix(&M);//销毁稀疏矩阵M;TransposeSMatrix(M);//求稀疏矩阵的转置矩阵AddSMatrix(&M,&N);//求稀疏矩阵M和N之和MulSMatrix(&M,&N);//求稀疏矩阵M和N之积}ADT SparseMatrix2、存储结构选择采用十字链表存储稀疏矩阵,它是稀疏矩阵链式表示的一种较好的表示方法。

稀疏矩阵 加法 链表

稀疏矩阵 加法 链表

稀疏矩阵加法链表稀疏矩阵加法是计算机科学领域中经常使用的一种算法,它的优势在于可以使用链表来代表稀疏矩阵,从而提高了计算的效率。

本文将介绍稀疏矩阵加法和链表的相关知识,并分步骤阐述稀疏矩阵加法链表的算法过程。

一、稀疏矩阵稀疏矩阵是指矩阵中大部分元素都是0的矩阵,他们在实际应用中常常出现,例如在图像处理、网络流分析等领域中。

为了避免浪费空间和资源,对于稀疏矩阵的存储和计算的方法需要特殊处理。

二、链表链表是一种由一系列结点组成的数据结构,结点之间通过指针相互连接。

链表的优势在于可以灵活地插入、删除结点,并且占用的空间相对更加紧凑。

因此,链表是表示稀疏矩阵的一种优秀的数据结构选择。

三、算法过程稀疏矩阵加法的过程与普通矩阵加法相似,只不过在计算过程中需要注意稀疏元素的位置和数量。

算法的具体步骤如下:1.创建链表:首先,需要使用链表来表示稀疏矩阵。

链表中的每个结点对应矩阵中的一个非零元素,结点分别保存行号、列号和非零元素的值。

链表需要按照行号递增的顺序排列。

2.读取输入:读取两个需要相加的稀疏矩阵,将它们转换为链表的形式,并按照行号递增的顺序排列。

3.遍历链表:接着从链表的头部开始遍历两个链表,将相同位置的元素相加。

具体而言,如果两个结点的行号和列号相同,则将两个元素的值相加,并将结果保存在一个新的链表中。

4.合并链表:最后将所有剩余的元素添加到结果链表中。

5.输出结果:输出结果链表所表示的矩阵。

四、时间复杂度稀疏矩阵加法链表的时间复杂度取决于两个输入矩阵中的非零元素数量,以及链表遍历的次数。

由于稀疏矩阵通常包含大量的0,因此非零元素的数量相对较小,从而可以大大提高计算效率。

在最坏情况下,算法的时间复杂度为$O(n)$,其中n表示两个稀疏矩阵中的非零元素数量的总和。

五、总结稀疏矩阵加法链表是一种高效的算法,它能够利用链表的特性来存储和计算稀疏矩阵。

通过链表的方式,可以避免浪费大量的内存和空间,同时提高了计算的效率。

稀疏矩阵的十字链表

稀疏矩阵的十字链表

稀疏矩阵的十字链表
稀疏矩阵是指在大多数元素都为零的情况下,只有少部分元素非零的矩阵。

与之相对应的是稠密矩阵,即大多数元素都非零的矩阵。

为了节省存储空间,我们可以采用特殊的数据结构来存储稀疏矩阵。

其中,十字链表是一种常用的数据结构。

十字链表是一种链式存储结构,用于存储稀疏矩阵。

它的基本思想是先将矩阵按行分解成一组行链表,再将矩阵按列分解成一组列链表。

每个非零元素在行链表和列链表中各有一个结点,这个结点包括该元素在矩阵中的行、列编号以及该元素的值。

通过行链表和列链表,我们可以快速地访问矩阵中的非零元素。

具体来说,十字链表包括两种结点,分别为行结点和列结点。

行结点的数据成员包括该非零元素所在的行号、列号、该元素的值,以及指向同一行中下一个非零元素的指针和同一列中下一个非零元素的指针。

列结点的数据成员包括该非零元素所在的行号、列号、该元素的值,以及指向同一列中下一个非零元素的指针和同一行中下一个非零元素的指针。

通过这样的链式存储结构,我们可以实现在O(k)的时间复杂度内访问矩阵中任意一个非零元素,其中k为矩阵中非零元素的个数。

总的来说,十字链表是一种用于存储稀疏矩阵的高效数据结构,它采用链式存储方式,能够快速地访问矩阵中的非零元素,并且能够有效地节省存储空间。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

-3-
new 0
2014年7月20日 22:21
} void main() { CrossList *CL; CL = (CrossList *)malloc(sizeof(CrossList)); CL = CreatCrossList(CL); CrossListDisplay(CL,RowRight); printf("编译通过\n"); }
new 0
2014年7月20日 22:21
#include <stdio.h> #include <malloc.h>
enum RowOrCol{RowRight,ColDown}; typedef int ElemType; typedef struct OLNode { int row,col; ElemType value; struct OLNode *down; struct OLNode *right; }OLNode; typedef OLNode* OLink; typedef struct CrossList { OLink *rowhead,*colhead;//指向存储每一行,每一列头指针空间的指针 int rows,cols,nums; //总行数列数,非零总数 }CrossList; CrossList * CreatCrossList(CrossList *CL) { int cols = 0,rows = 0; int row = 0,col = 0,value = 0; int i,j; OLNode *p,*q; //------------------------------十字表初始化 printf("请输入总行数与总列数\n"); scanf("%d",&rows); scanf("%d",&cols); CL->rows = rows; CL->cols = cols; CL->nums = 0;
-4-
-2-
new 0
2014年7月20日 22:21
} //------------------------总结点(非零)数加1 CL->nums++; }
return CL; } void CrossListDisplay(CrossList *CL,RowOrCol choose) { int i; OLink p; if(choose == RowRight) { printf("行先序输出\n"); printf("row\tcol\tvalue\n"); for(i = 0; i < CL->rows; i++) { if(CL->rowhead[i] != NULL) { p = CL->rowhead[i]; while(p != NULL) { printf("%d\t",p->row); printf("%d\t",p->col); printf("%d\n",p->value); p = p->right; } } } } if(choose == ColDown) { printf("\n列先序输出\n"); for(i = 0; i < CL->cols; i++) { if(CL->colhead[i] != NULL) { p = CL->colhead[i]; while(p != NULL) { printf("%d\t",p->col); printf("%d\t",p->row); printf("%d\n",p->value); p = p->down; } } } }
-1-
new 0
2014年7月20日 22:21
p = (OLNode *)malloc(sizeof(OLNode)); printf("亲,请输入行和列与非零数值\n"); ROWGO: printf("行数为: "); scanf("%d",&row); if(row == -1) break; if(row < -1 || row > rows) { printf("行数越界,请重新输入\n"); goto ROWGO; } COLGO: printf("列数为: "); scanf("%d",&col); if(col < 0 || col > cols) { printf("列数越界,请重新输入\n"); goto COLGO; } printf("非零数值为: "); scanf("%d",&value); p->row = row; p->col = col; p->value = value; p->right = NULL; p->down = NULL; //---------------------------添加到这一行的末尾 if(CL->rowhead[row] == NULL) CL->rowhead[row] = p; else { q = CL->rowhead[row]; while(q->right != NULL) { q = q->right; } p->right = q->right; q->right = p; } //-------------------------添加到这一列的末尾 if(CL->colhead[col] == NULL) CL->colhead[col] = p; else { q = CL->colhead[col]; while(q->down != NULL) { q = q->down; } p->down = q->down; q->down = p;
//--------------------------------所有行指针初始化 CL->rowhead = (OLink *)malloc(rows * sizeof(OLink)); return NULL; for(i = 0; i < rows; i++) CL->rowhead[i] = NULL; //-------------------------------所有列指针初始化 CL->colhead = (OLink *)malloc(cols * sizeof(OLink)); if(CL->colhead == NULL) return NULL; for(j = 0; j < cols; j++) CL->colhead[j] = NULL; printf("输入所有非零数,行输入为-1时退出输入\n"); //-------------------------------增加结点(非零数) while(1) {
相关文档
最新文档