用三元组表示稀疏矩阵的乘法
三元组实现稀疏矩阵的相乘
三元组实现稀疏矩阵的相乘学院:班级:姓名:学号:一、实验题目:建立三元组,并以三元组为储存结构储存两个稀疏矩阵,并实现他们的相乘,输出结果。
二、需求分析:定义一个一维数组,它用来以行序为主序依次存放所有非零元构成的三元组,并定义变量分别记录矩阵的行数、列数非零元个数以及数组大小。
按照这种方式定义三元组的数据实现两个稀疏矩阵的乘法操作。
三、概要设计:建立一个三元组的结点:struct Node{int Row,Col; // 三元组Á的行列号?int Value; // 元素的值};用以储存稀疏矩阵,建立A和B两个稀疏矩阵用三元组表来储存非零元的行数、列数、值,再相乘输出结果。
四、详细设计:建立三元组:struct Node{int Row,Col; // 三元组Á的行列号?int Value; // 元素的值};建立三元组表:struct SparMatrix{int Rows,Cols; // 矩的行列数int Terms; // 矩阵的非零元个数struct Node arrayData[MAX_SIZE]; // 存放矩阵非零元素的三元组数组void PrintMatrix(); // 输出矩阵int GetElement(int m ,int n); // 获得矩阵对应的元素void PrintInit(); // 矩阵的输初始化void AddElement(int m,int n, int Value); // 增加非零元素};矩阵相乘:SparMatrix* MatrixMulti(SparMatrix* pM1,SparMatrix* pM2);void main(){SparMatrix matrix1;cout<<"The 1st matrix:"<<endl;matrix1.PrintInit();SparMatrix matrix2;cout<<"The 2nd matrix:"<<endl;matrix2.PrintInit();cout<<"Multiplication:"<<endl;matrix1.PrintMatrix();cout<<"*"<<endl;matrix2.PrintMatrix();cout<<"="<<endl;SparMatrix* pMatrixPro;pMatrixPro = MatrixMulti(&matrix1,&matrix2);if (pMatrixPro == NULL){cout<<"Error!"<<endl;}else{pMatrixPro->PrintMatrix();}if (pMatrixPro != NULL){delete pMatrixPro;pMatrixPro = NULL;}}五、程序使用说明:首先会看到“Please input the row and col num, using space to separate them:”的字样,这时候请输入你所要建立稀疏矩阵行数列数。
用三元组表示稀疏矩阵的乘法
图5.17给出了一个矩阵相乘的例子。当矩阵M、N是稀疏 矩阵时,我们可以采用三元组表的表示形式来实现矩阵的相 乘。
3 0 0 5
0 2
1 0
M 0 1 0 0 N
2 0 0 0
2 4
0 0
0 6
Q 1 0
0 4
图5.17 Q=M×N
图5.18 矩阵M、N、Q的三元组表
{
OLink * row_head, *col_head; /* 行、 列链表的头指针向量 */
int m, n, len; /* 稀疏矩阵的行数、 列数、 非零元素的个数 */
}CrossList;
CreateCrossList (CrossList * M) {/* 采用十字链表存储结构, 创建稀疏矩阵M */ scanf(&m, &n, &t); /* 输入M的行数, 列数和非零元素的个数 */ M->m=m; M->n=n; M->len=t; If(!(M->row_head=(OLink * )malloc((m+1)sizeof(OLink)))) exit(OVERFLOW); If(!(M->col_head=(OLink * )malloc((n+1)sizeof(OLink)))) exit(OVERFLOW); M->row_head[ ]=M->col_head[ ]=NULL;
}TriSparMatrix;
具体算法如下:
该算法的时间主要耗费在乘法运算及累加上,其时间复杂度为O (A.len×B.n)。当A.len 接近于A.m×A.n时,该算法时间复杂度接近于 经典算法的时间复杂度O(A.m×A.n×B.n)。
实验报告五:稀疏矩阵的三元组实现实验
实验报告
实验五稀疏矩阵的三元组实现实验(4学时)
实验目的:
掌握稀疏矩阵的三元组表示方法、算法实现。
实验内容:(类C算法的程序实现,任选其二)
(1) 基于三元组的稀疏矩阵表示与输入、输出方法(必做);
(2) 基于三元组的稀疏矩阵加法(选做);
(3) 基于三元组表示的稀疏矩阵转置(选做);
(4) 基于三元组表示的稀疏矩阵的乘法(选做)。
实验准备:
1) 计算机设备;2) 程序调试环境的准备,如TC环境;3) 实验内容的算法分析与代码设计与分析准备。
实验步骤:
1.录入程序代码并进行调试和算法分析;
2.编写实验报告。
实验结果:
试验的完整的C程序代码,以及程序实现与结果分析。
源程序:
1,三元组的顺序表存储表示
2,创建一个稀疏矩阵
3,表示这个矩阵
4,主函数
最终结果:。
三元组矩阵乘法
三元组矩阵乘法1. 任务背景矩阵是线性代数中一个非常重要的概念,广泛应用于各个领域,包括数学、物理、计算机科学等。
矩阵乘法是其中的一个基本运算,它在很多领域都有着重要的应用。
而三元组矩阵乘法则是矩阵乘法的一种特殊形式,它可以更加高效地表示和计算稀疏矩阵的乘法运算。
2. 任务介绍2.1 什么是三元组矩阵?三元组矩阵是一种特殊的矩阵表示方法,适用于稀疏矩阵(大部分元素为0)的存储和计算。
在三元组矩阵中,只存储非零元素的值及其对应的行列索引,而忽略了所有零元素。
这样可以大大减少存储空间和计算复杂度。
三元组矩阵的存储方式通常采用三个数组来表示,分别是:values、row_indices和col_indices。
其中,values数组存储非零元素的值,row_indices数组存储非零元素所在的行索引,col_indices数组存储非零元素所在的列索引。
2.2 三元组矩阵乘法的定义给定两个三元组矩阵A和B,它们的乘积C的定义如下:C(i, j) = sum(A(i, k) * B(k, j)) for k in range(0, n)其中,n表示矩阵的维度,A(i, k)表示矩阵A的第i行第k列的元素,B(k, j)表示矩阵B的第k行第j列的元素。
2.3 三元组矩阵乘法的算法三元组矩阵乘法的算法可以分为两个步骤:稀疏矩阵的转置和乘法计算。
2.3.1 稀疏矩阵的转置为了实现高效的三元组矩阵乘法,需要先将矩阵B进行转置。
转置后的矩阵B的非零元素行列索引互换,即原来的B(k, j)变为B(j, k)。
2.3.2 乘法计算在转置后的矩阵B上进行乘法计算。
对于矩阵A的每一行i,找到矩阵B中列索引等于i的所有非零元素,然后将这些元素与A(i, k)相乘,并将结果累加得到C(i, j)。
2.4 三元组矩阵乘法的优势相比于传统的矩阵乘法算法,三元组矩阵乘法具有以下优势:•节省存储空间:三元组矩阵只存储非零元素,大大减少了存储空间的占用。
稀疏矩阵基本操作 实验报告
稀疏矩阵基本操作实验报告一、实验内容稀疏矩阵的压缩储存结构,以及稀疏矩阵的三元组表表示方法下的转置、相加、相乘等算法二、实验目的1.熟悉数组、矩阵的定义和基本操作2.熟悉稀疏矩阵的储存方式和基本运算3.理解稀疏矩阵的三元组表类型定义,掌握稀疏矩阵的输入、输出和转置算法三、实验原理1.使用三元组储存矩阵中的非零元素(三元组分别储存非零元素的行下标,列下标和元素值)。
除了三元组表本身,储存一个稀疏矩阵还需要额外的三个变量,分别储存矩阵的非零元个数,矩阵的行数和矩阵的列数。
2.稀疏矩阵的创建算法:第一步:根据矩阵创建一个二维数组,表示原始矩阵第二步:取出二维数组中的元素(从第一个元素开始取),判断取出元素是否为非零元素,如果为非零元素,把该非零元素的数值以及行下标和列下表储存到三元数组表里,否则取出下一个元素,重复该步骤。
第三步:重复第二步,知道二维数组中所有的元素已经取出。
3.稀疏矩阵倒置算法:第一步:判断进行倒置的矩阵是否为空矩阵,如果是,则直接返回错误信息。
第二步:计算要倒置的矩阵每列非零元素的数量,存入到num数组(其中num[i] 代表矩阵中第i列非零元素的个数)。
以及倒置后矩阵每行首非零元的位置,存入cpot 数组中(其中cpot表示倒置后矩阵每行非零元的位置,对应表示原矩阵每列中第一个非零元的位置)。
第三步:确定倒置后矩阵的行数和列数。
第四步:取出表示要导致矩阵中三元组表元素{e, I, j}(第一次取出第一个,依次取出下一个元素),从第二步cpot数组中确定该元素倒置后存放的位置(cpot[j]),把该元素的行下标和列下标倒置以后放入新表的指定位置中。
cpot[j] 变量加一。
第五步:重复第四步,直到三元组表中所有的元素都完成倒置。
第六步:把完成倒置运算的三元组表输出。
4.稀疏矩阵加法算法:第一步:检查相加两个矩阵的行数和列数是否相同,如果相同,则进入第二步,否则输出错误信息。
第二步:定义变量i和j,用于控制三元组表的遍历。
三元组实现稀疏矩阵加减乘
#include<stdio.h>#include<stdlib.h> #define MAXSIZE 12500 // 三元组结构typedef structinti,j;int e; }Triple;{//矩阵行下标和列下标//值typedef struct {Triple data[MAXSIZE+1];int rpos[MAXSIZE+1]; // 这是存放各行第一非零元在矩阵中的位置int mu,nu,tu; // 矩阵的行数、列数、非零元个数}Matrix;void Init(Matrix* M);void Add(Matrix* M,Matrix* T,Matrix* G);void Jian(Matrix* M,Matrix* T,Matrix* G);void Cheng(Matrix* M,Matrix* T,Matrix* G);void Cheng(Matrix* M,Matrix* T,Matrix* G); void PrintMatrix(Matrix* M);//2、初始化矩阵void Init(Matrix* M){int i;if(M->mu < 1 || M->nu < 1 || M->tu > M->mu*M->nu){printf(" 出错!\n"); //如果矩阵的行数、列数不符合要求,打印出错} for(i=1;i<=M->tu;i++) //data[0] 不用{printf(“第%d个非零元的行号:“,i); //以下为数据初始化scanf("%d",&M->data[i].i);printf(“第%d个非零元的列号:",i); scanf("%d",&M->data[i].j); printf(”第%d个非零元的元素值:",i); scanf("%d",&M->data[i].e);}printf("\n");printf(" 您创建的矩阵如下:\n"); PrintMatrix(M);} //3、矩阵相加void Add(Matrix* M,Matrix* T,Matrix* G) {G->mu = M->mu;的行、列数。
稀疏矩阵的存储和乘法操作
稀疏矩阵的存储和乘法操作⼀稀疏矩阵的存储1.三元组顺序表三元组表⽰法就是在存储⾮零元的同时,存储该元素所对应的⾏下标和列下标。
稀疏矩阵中的每⼀个⾮零元素由⼀个三元组(i,j,a ij)唯⼀确定。
矩阵中所有⾮零元素存放在由三元组组成的顺序表中(通常⽤数组)。
所以三元组的逻辑结构如下://————稀疏矩阵的三元组表⽰法————//#define MAX_SIZE 1500 //表⽰稀疏矩阵的⾮零元素的最⼤个数class Triple{int i,j;//表⽰⾮零元素的⾏下表和列下标int val;//⾮零元素的值,此处以int类型为例};class TSMatrix{Triple data[MAX_SIZE];int row_num,col_num,cnt;//稀疏矩阵的⾏数、列数以及⾮零元素的个数};注意,此处的⾮零元素的三元组是以⾏序为主序顺序排列的。
2.⾏逻辑链接顺序表⾏逻辑链接顺序表的实质就是在三元组顺序表的基础上加了⼀个数组,这个数组⽤于存储稀疏矩阵中每⾏的第⼀个⾮零元素的在三元组顺序表中的位置(此处⼀定要理解对,是在三元组顺序表中的位置)。
所以其逻辑结构如下://————稀疏矩阵的⾏逻辑链接表⽰法————//#define MAX_SIZE 1500 //表⽰稀疏矩阵的⾮零元素的最⼤个数#define MAX_ROW 1500 //表⽰稀疏矩阵的⾏数的最⼤个数class Triple{int i,j;//表⽰⾮零元素的⾏下表和列下标int val;//⾮零元素的值,此处以int类型为例};class RLSMatrix{Triple data[MAX_SIZE]; //⾮零元三元组表int rpos[MAX_ROW];//每⾏第⼀个⾮零元素的位置int row_num,col_num,cnt;//稀疏矩阵的⾏数、列数以及⾮零元素的个数};3.⼗字链表当稀疏矩阵的⾮零元个数和位置在操作过程中变化较⼤时,就不易采⽤顺序存储结构来表⽰三元组的线性表。
数据结构三元组稀疏矩阵乘法代码
数据结构三元组稀疏矩阵乘法代码代码:```pythonclass SparseMatrix:def __init__(self, rows, columns):self.rows = rowsself.columns = columnsself.elements = []def insert(self, row, column, value):if row >= 0 and row < self.rows and column >= 0 and column < self.columns:self.elements.append((row, column, value))else:raise IndexError("Invalid index")def multiply(self, other):if self.columns != other.rows:raise ValueError("Invalid matrix dimensions")result_matrix = SparseMatrix(self.rows, other.columns)for i in range(self.rows):for j in range(other.columns):result = 0for k in range(len(self.elements)):if self.elements[k][0] == i:for l in range(len(other.elements)):if other.elements[l][1] == j:if self.elements[k][1] == other.elements[l][0]:result += self.elements[k][2] * other.elements[l][2] if result != 0:result_matrix.insert(i, j, result)return result_matrix# 创建稀疏矩阵1sparse_matrix1 = SparseMatrix(3, 3)sparse_matrix1.insert(0, 0, 1)sparse_matrix1.insert(0, 2, 2)sparse_matrix1.insert(1, 1, 3)sparse_matrix1.insert(2, 0, 4)# 创建稀疏矩阵2sparse_matrix2 = SparseMatrix(3, 3)sparse_matrix2.insert(0, 1, 5)sparse_matrix2.insert(1, 0, 6)sparse_matrix2.insert(1, 2, 7)sparse_matrix2.insert(2, 2, 8)# 稀疏矩阵乘法result = sparse_matrix1.multiply(sparse_matrix2)# 输出结果for i in range(result.rows):for j in range(result.columns):print(result.elements[i * result.columns + j][2], end=" ")print()```该代码实现了三元组表示的稀疏矩阵的乘法运算。
稀疏矩阵相乘
right 存放行链表指针。
整个稀疏矩阵定义为类 Matrix 的一个对象,*headnode 给出整个附加头结点链表的附
加头结点的地址。
headHale Waihona Puke downnext right
head down
row value
col rig非ht零元素结点
附加头结点
2.2 主要算法
非零元素结点
基于三元组及十字链表的稀疏矩阵乘法 Matrix Matrix::Mul( Matrix b) //矩阵乘法的实现
.
稀疏矩阵相乘
1 问题描述
1.1 稀疏矩阵的三元组及十字链表表示
(1)稀疏矩阵及其三元组表示 稀疏矩阵
0 0 0 22 0 0 15
0 11 0 0 0 17 0
0
0
0 6 0 0
0
0 0 0 0 0 39 0
91 0
0 0
0 28
0 0
0 0
0 0
0 0
行(row) 列(col) 值(value)
{
if(this->Col==b.Row)
{ Matrix C(this->Row,b.Col); //以 A 矩阵的行和 b 矩阵的列为行列建立稀疏矩阵
float value; node *Row_head,*Col_head; //设两个指针,一个充当行头指针,一个为列指针 for(int i=1;i<=temp;i++) //先确定行,再求出 C 矩阵在该行各列的元素
[0]
0
3
22
[1]
0
6
15
[2]
1
1
11
三元组实现稀疏矩阵加减乘
m++;
g++;
}
while(T->data[t].i == k) //插入T的元素
{
G->data[g].i = k;
G->data[g].j = T->data[t].j;
G->data[g].e = 0 - T->data[t].e;
}
printf("\n");
printf("您创建的矩阵如下:\n");
PrintMatrix(M);
}
//3、矩阵相加
void Add(Matrix* M,Matrix* T,Matrix* G)
{
G->mu = M->mu; //因为加减运算必须维数相等,所以M、T行、列数相等,初始化第三方矩阵的行、列数。
}
printf("\n");
printf("相加后的矩阵如下:\n");
PrintMatrix(G);
}
//4、矩阵相减
void Jian(Matrix* M,Matrix* T,Matrix* G)
{
G->mu = M->mu;
#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 12500
//三元组结构
三元组压缩存储结构的稀疏矩阵的运算快速转置
三元组压缩存储结构的稀疏矩阵的运算快速转置在计算机科学和数学领域中,稀疏矩阵是一种在大部分元素为零的矩阵。
由于其大部分元素为零,因此在存储和运算时存在着一些挑战。
为了解决这一问题,人们提出了三元组压缩存储结构,这种存储结构能够有效地压缩稀疏矩阵,并且能够实现快速的运算转置。
1.稀疏矩阵稀疏矩阵是一种大部分元素为零的矩阵,与之相对应的是稠密矩阵,其大部分元素为非零值。
稀疏矩阵通常在图像处理、文本处理、网络分析等领域中得到广泛应用。
然而,由于大部分元素为零,传统的存储方式会导致存储空间的浪费。
人们提出了三元组压缩存储结构,以解决稀疏矩阵存储的问题。
2.三元组压缩存储结构三元组压缩存储结构是一种用于表示稀疏矩阵的存储格式。
它采用三个数组来分别存储矩阵的非零元素的行坐标、列坐标和数值。
由于只需存储非零元素的信息,因此能够有效地压缩存储空间。
三元组压缩存储结构还能够实现快速的随机访问,这是由于它将矩阵的元素位置和数值分开存储,使得在进行运算时能够更为高效。
3.稀疏矩阵的运算稀疏矩阵的运算是对稀疏矩阵进行加法、减法、乘法等操作的过程。
在进行稀疏矩阵的运算时,三元组压缩存储结构能够显著提高计算效率。
这是由于在进行运算时,只需考虑非零元素,而无需考虑大量的零元素,从而减少了计算的复杂度。
4.稀疏矩阵的快速转置稀疏矩阵的转置是将矩阵的行和列交换,同时保持非零元素的位置和数值不变。
在传统的存储方式下,稀疏矩阵的转置操作相对复杂且耗时。
然而,采用三元组压缩存储结构后,稀疏矩阵的快速转置变得十分简便。
通过交换三元组中的行坐标和列坐标,即可完成稀疏矩阵的快速转置操作。
5.个人观点和理解我认为三元组压缩存储结构的出现,极大地解决了稀疏矩阵在存储和运算中的效率问题。
通过将矩阵的非零元素信息进行压缩存储,不仅节省了存储空间,同时也提高了计算效率。
在实际应用中,三元组压缩存储结构能够更好地满足对存储空间和计算效率有较高要求的场景,为稀疏矩阵的处理提供了更为便利和高效的途径。
c语言以三元顺序表表示稀疏矩阵
C语言以三元顺序表表示稀疏矩阵1. 引言稀疏矩阵是指大部分元素为零的矩阵,通常在实际应用中占据大量存储空间。
为了高效处理稀疏矩阵,我们通常会采用三元组顺序表的方式进行表示。
本文将探讨如何使用C语言以三元顺序表表示稀疏矩阵,深入理解其原理和实现方法。
2. 稀疏矩阵的表示方法在C语言中,我们可以使用三元组顺序表来表示稀疏矩阵。
三元组顺序表包括三个部分:行号、列号和元素值。
通过这种方式,我们可以有效地压缩稀疏矩阵,节省存储空间,并且方便进行相关的运算。
3. 三元顺序表的数据结构在C语言中,我们可以使用结构体来定义三元顺序表的数据结构。
具体而言,我们可以定义一个包含行号、列号和元素值的结构体,然后通过数组来存储这些结构体,从而表示整个稀疏矩阵。
4. 如何实现C语言表示稀疏矩阵在C语言中,我们可以通过以下步骤来实现稀疏矩阵的表示:1. 定义一个结构体来存储稀疏矩阵的三元组信息。
2. 创建一个数组,用来存储这些结构体,从而表示整个稀疏矩阵。
3. 编写相关的函数,实现稀疏矩阵的压缩、展开以及相关的运算操作。
5. 样例代码下面是一段简单的C语言代码,用来表示一个稀疏矩阵,并进行相关的计算操作:```#include <stdio.h>#define MAXSIZE 12500// 定义三元组结构体typedef struct {int row;int col;int value;} Triple;// 定义稀疏矩阵typedef struct {Triple data[MAXSIZE + 1]; // 0号单元存储矩阵的行数、列数和非零元个数int mu, nu, tu; // 矩阵的行数、列数和非零元个数} TSMatrix;// 主函数int main() {// 在这里编写相关的稀疏矩阵操作return 0;}```6. 总结与展望通过本文的讨论,我们深入了解了C语言以三元顺序表表示稀疏矩阵的原理和实现方法。
稀疏矩阵相乘
稀疏矩阵相乘1问题描述稀疏矩阵的三元组及十字链表表示(1)稀疏矩阵及其三元组表示 稀疏矩阵(2)稀疏矩阵的十字链表表示基本要求(1)以“带行逻辑链接信息”的三元组表示稀疏矩阵; (2)输入矩阵用三元组顺序输入; (2)稀疏矩阵采用十字链表表示;(3)实现两个矩阵相乘的运算,而运算结果的矩阵则以通常的阵列形式列出。
2设计思路行(row) 列(col) 值(value)[0] 0 3 22 [1] 0 6 15 [2] 1 1 11 [3] 1 5 17 [4] 2 3 -6 [5] 3 5 39 [6] 4 0 39 [7]52280000280000000091039000000006000017000110150022000⎪⎪⎪⎪⎪⎪⎪⎪⎭⎫⎝⎛-存储结构设计三元组表示稀疏矩阵只存储矩阵中极少的非零元素,采用<row,col,value>来唯一地确定每一个非零元素,其中row、col、value分别表示非零元素在矩阵中的的行下标、列下表和值。
各数组元素的三元组按在原矩阵中的位置以行优先的顺序依次存放。
struct triple{ //三元组结构定义int row, col; //非零元素行号,列号Float value; //非零元素的值triple& operator=(triple &x){row=;col=;value=;}};十字链表表示稀疏矩阵struct element{ int row,col;float value;};class Matrix;class node{ // 矩阵节点类的定义friend class Matrix;public:node():head(true){ right=down=this;} //建立附加头结点node(element *t) // 建立非零元素结点{=t->col;=t->row;=t->value;right=down=this;head=false;}node*down,*right;//行列链表指针bool head;union{ element triple;node*next;}; //无名联合};class Matrix{//稀疏矩阵的类定义friend istream&operator>>(istream&,Matrix&);friend ostream&operator<<(ostream&,Matrix&);private: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); //插入矩阵元素node *Locate(int i); //定位附加头结点Matrix Mul(Matrix b); //两个矩阵相乘Matrix &operator=(Matrix &T); //重载赋值号};在稀疏矩阵的十字链表表示中,矩阵的的每一行设置为一个带附加头结点的循环行链表,每一列也设置为一个带附加头结点的循环列链表。
数据结构三元组完成版
for(j=1;j<=N.nu;j++)
if(*(Qe+(i-1)*l+j-1)!=0)
{
Qn++;
(*Q).data[Qn].e=*(Qe+(i-1)*l+j-1);
(*Q).data[Qn].i=i;
(*Q).data[Qn].j=j;
}
free(Qe);
return 1;
}
//求稀疏矩阵的乘积Q=M*N
int MultSMatrix(TSMatrix M,TSMatrix N,TSMatrix *Q)
{
int i,j,h=M.mu,l=N.nu,Qn=0;
// h,l分别为矩阵Q的行、列值,Qn为矩阵Q的非零元素个数,初值为0
ElemType *Qe;
(*Q).tu=Qn;
return 1;
}
//按位查找法
//求稀疏矩阵M的转置矩阵T。
int TransposeSMatrix(TSMatrix M,TSMatrix *T)
{
int p,q,col;
(*T).mu=M.nu;
(*T).nu=M.mu;
(*T).tu=M.tu;
if((*T)tu)
{
do
{
printf("请按行序顺序输入第%d个非零元素所在的行(1~%d),"
"列(1~%d),元素值:(逗号)\n", i,(*M).mu,(*M).nu);
scanf("%d,%d,%d",&m,&n,&e);
实现稀疏矩阵采用三元组表示的基本运算实验报告
实现稀疏矩阵(采用三元组表示)的基本运算实验报告实现稀疏矩阵(采用三元组表示)的基本运算实验报告一实验题目: 实现稀疏矩阵(采用三元组表示)的基本运算二实验要求:(1)生成如下两个稀疏矩阵的三元组a 和 b;(上机实验指导 P92 )(2)输出 a 转置矩阵的三元组;(3)输出a + b 的三元组;(4)输出 a * b 的三元组;三实验内容:3.1 稀疏矩阵的抽象数据类型:ADT SparseMatrix {数据对象:D={aij| i = 1,2,3,….,m; j =1,2,3,……,n;ai,j∈ElemSet,m 和n分别称为矩阵的行数和列数 }数据关系 : R={ Row , Col }Row ={<ai,j ,ai,j+1> | 1≤ i≤m , 1≤ j ≤ n-1}Col ={<a i,j , a i+1,j >| 1≤i≤m-1,1≤j ≤n}基本操作:CreateSMatrix(&M)操作结果:创建稀疏矩阵M PrintSMatrix(M)初始条件:稀疏矩阵M已经存在操作结果:打印矩阵M DestroySMatrix(&M)初始条件:稀疏矩阵M已经存在操作结果:销毁矩阵M CopySMatrix(M, &T)初始条件:稀疏矩阵M已经存在操作结果:复制矩阵M到TAddSMatrix(M, N, &Q)初始条件:稀疏矩阵M、N已经存在操作结果:求矩阵的和Q=M+N SubSMatrix(M, N, &Q)初始条件:稀疏矩阵M、N已经存在操作结果:求矩阵的差Q=M-N TransposeSMatrix(M, & T)初始条件:稀疏矩阵M已经存在操作结果:求矩阵M的转置T MultSMatrix(M, N, &Q)初始条件:稀疏矩阵M已经存在操作结果:求矩阵的积Q=M*N }ADT SparseMatrix3.2存储结构的定义#define N 4typedef int ElemType;#define MaxSize 100 //矩阵中非零元素最多个数typedef struct{ int r; //行号int c; //列号ElemType d; //元素值} TupNode; //三元组定义typedef struct{ int rows; //行数值int cols; //列数值int nums; //非零元素个数TupNode data[MaxSize];} TSMatrix; //三元组顺序表定义3.3基本操作实现:void CreatMat(TSMatrix &t,ElemType A[N][N]){int i,j;t.rows=N;t.cols=N;t.nums=0;for (i=0;i<N;i++){for (j=0;j<N;j++)if (A[i][j]!=0){t.data[t.nums].r=i;t.data[t.nu ms].c=j;t.data[t.nums].d=A[i][j];t.nums++;}}}void DispMat(TSMatrix t){int i;if (t.nums<=0)return;printf("\t%d\t%d\t%d\n",t.rows ,t.cols,t.nums);printf("\t------------------\n ");for (i=0;i<t.nums;i++)printf("\t%d\t%d\t%d\n",t.data[i] .r,t.data[i].c,t.data[i].d);3.4解题思路:1.转置矩阵:只要判定原矩阵有值,那么只要遍历一遍原矩阵,把原来矩阵中非0元素行列变换一下赋值到新的矩阵中即可。
稀疏矩阵的加法,三元组实现矩阵的乘法
#include <iostream>#include <iomanip>using namespace std;const int MAXSIZE=100; // 定义非零元素的对多个数const int MAXROW=10; // 定义数组的行数的最大值typedef struct { // 定义三元组的元素int i,j;int e;}Triple;typedef struct { // 定义普通三元组对象Triple data[MAXSIZE+1];int mu,nu,tu;}TSMatrix;typedef struct { // 定义带链接信息的三元组对象Triple data[MAXSIZE+2];int rpos[MAXROW+1];int mu,nu,tu;}RLSMatrix;template <class P>bool InPutTSMatrix(P & T,int y){ //输入矩阵,按三元组格式输入cout<<"输入矩阵的行,列和非零元素个数:"<<endl;cin>>T.mu>>T.nu>>T.tu;cout<<"请输出非零元素的位置和值:"<<endl;int k=1;for(;k<=T.tu;k++)cin>>T.data[k].i>>T.data[k].j>>T.data[k].e;return true;}template <class P>bool OutPutSMatrix(P T){ // 输出矩阵,按标准格式输出int m,n,k=1;for(m=0;m<T.mu;m++){for(n=0;n<T.nu;n++){if((T.data[k].i-1)==m&&(T.data[k].j-1)==n){cout.width(4);cout<<T.data[k++].e;}else{cout.width(4); cout<<"0"; }}cout<<endl;}return true;}// 求矩阵的转置矩阵bool TransposeSMatrix( ){TSMatrix M,T; //定义预转置的矩阵InPutTSMatrix(M, 0); //输入矩阵int num[MAXROW+1];int cpot[MAXROW+1]; // 构建辅助数组int q,p,t;T.tu=M.tu; T.mu=M.nu; T.nu=M.mu;if(T.tu){for(int col=1;col<=M.nu;col++) num[col]=0;for(t=1;t<=M.tu;t++) ++num[M.data[t].j];cpot[1]=1;for(int i=2;i<=M.nu;i++) cpot[i]=cpot[i-1]+num[i-1]; // 求出每一列中非零元素在三元组中出现的位置for(p=1;p<=M.tu;p++){col=M.data[p].j; q=cpot[col];T.data[q].i=col; T.data[q].j=M.data[p].i;T.data[q].e=M.data[p].e; ++cpot[col];}}cout<<"输入矩阵的转置矩阵为"<<endl;OutPutSMatrix(T);return true;}bool Count(RLSMatrix &T){int num[MAXROW+1];for(int col=1;col<=T.mu;col++) num[col]=0;for(col=1;col<=T.tu;col++) ++num[T.data[col].i];T.rpos[1]=1;for(int i=2;i<=T.mu;i++) T.rpos[i]=T.rpos[i-1]+num[i-1]; // 求取每一行中非零元素在三元组中出现的位置return true;}// 两个矩阵相乘bool MultSMatrix ( ){RLSMatrix M,N,Q; // 构建三个带“链接信息”的三元组表示的数组InPutTSMatrix(M,1); // 用普通三元组形式输入数组InPutTSMatrix(N,1);Count(M); Count(N);if(M.nu!=N.mu) return false;Q.mu=M.mu; Q.nu=N.nu; Q.tu=0; // Q初始化int ctemp[MAXROW+1]; // 辅助数组int arow,tp,p,brow,t,q,ccol;if(M.tu*N.tu){ // Q是非零矩阵for( arow=1;arow<=M.mu;arow++){///memset(ctemp,0,N.nu);for(int x=1;x<=N.nu;x++) // 当前行各元素累加器清零ctemp[x]=0;Q.rpos[arow]=Q.tu+1; // 当前行的首个非零元素在三元组中的位置为此行前所有非零元素+1if(arow<M.mu) tp=M.rpos[arow+1];else tp=M.tu+1;for(p=M.rpos[arow];p<tp;p++){ // 对当前行每个非零元素进行操作brow=M.data[p].j; // 在N中找到i值也操作元素的j值相等的行if(brow<N.mu) t=N.rpos[brow+1];else t=N.tu+1;for(q=N.rpos[brow];q<t;q++){ // 对找出的行当每个非零元素进行操作ccol=N.data[q].j;ctemp[ccol] += M.data[p].e*N.data[q].e; // 将乘得到对应值放在相应的元素累加器里面}}for(ccol=1;ccol<=Q.nu;ccol++) // 对已经求出的累加器中的值压缩到Q中if(ctemp[ccol]){if(++Q.tu>MAXSIZE) return false;Q.data[Q.tu].e=ctemp[ccol];Q.data[Q.tu].i=arow;Q.data[Q.tu].j=ccol;}}}OutPutSMatrix(Q);return true;}typedef struct OLNode{ // 定义十字链表元素int i,j;int e;struct OLNode *right,*down; // 该非零元所在行表和列表的后继元素}OLNode,*OLink;typedef struct{ // 定义十字链表对象结构体OLink *rhead,*chead;int mu,nu,tu; // 系数矩阵的行数,列数,和非零元素个数}CrossList;bool CreateSMatrix_OL(CrossList & M){ // 创建十字链表int x,y,m;cout<<"请输入矩阵的行,列,及非零元素个数"<<endl;cin>>M.mu>>M.nu>>M.tu;if(!(M.rhead=(OLink*)malloc((M.mu+1)*sizeof(OLink)))) exit(0);if(!(M.chead=(OLink*)malloc((M.nu+1)*sizeof(OLink)))) exit(0);for(x=0;x<=M.mu;x++)M.rhead[x]=NULL; // 初始化各行,列头指针,分别为NULLfor(x=0;x<=M.nu;x++)M.chead[x]=NULL;cout<<"请按三元组的格式输入数组:"<<endl;for(int i=1;i<=M.tu;i++){cin>>x>>y>>m; // 按任意顺序输入非零元,(普通三元组形式输入)OLink p,q;if(!(p=(OLink)malloc(sizeof(OLNode)))) exit(0); // 开辟新节点,用来存储输入的新元素p->i=x; p->j=y; p->e=m;if(M.rhead[x]==NULL||M.rhead[x]->j>y){p->right=M.rhead[x]; M.rhead[x]=p;}else{for(q=M.rhead[x];(q->right)&&(q->right->j<y);q=q->right); // 查找节点在行表中的插入位置p->right=q->right; q->right=p; // 完成行插入}if(M.chead[y]==NULL||M.chead[y]->i>x){p->down=M.chead[y]; M.chead[y]=p;}else{for(q=M.chead[y];(q->down)&&(q->down->i<x);q=q->down); // 查找节点在列表中的插入位置p->down=q->down; q->down=p; // 完成列插入}}return true;}bool OutPutSMatrix_OL(CrossList T){ // 输出十字链表,用普通数组形式输出for(int i=1;i<=T.mu;i++){OLink p=T.rhead[i];for(int j=1;j<=T.nu;j++){if((p)&&(j==p->j)){cout<<setw(3)<<p->e; p=p->right;}elsecout<<setw(3)<<"0";}cout<<endl;}return true;}//矩阵的加法bool AddSMatrix(){CrossList M,N; // 创建两个十字链表对象,并初始化CreateSMatrix_OL(M);CreateSMatrix_OL(N);cout<<"输入的两矩阵的和矩阵为:"<<endl;OLink pa,pb,pre ,hl[MAXROW+1]; //定义辅助指针,pa,pb分别为M,N当前比较的元素,pre为pa的前驱元素for(int x=1;x<=M.nu;x++) hl[x]=M.chead[x];for(int k=1;k<=M.mu;k++){ // 对M的每一行进行操作pa=M.rhead[k]; pb=N.rhead[k]; pre=NULL;while(pb){ // 把N中此行的每个元素取出,OLink p;if(!(p=(OLink)malloc(sizeof(OLNode)))) exit(0); // 开辟新节点,存储N中取出的元素p->e=pb->e; p->i=pb->i; p->j=pb->j;if(NULL==pa||pa->j>pb->j){ // 当M此行已经检查完或者pb因该放在pa 前面if(NULL==pre)M.rhead[p->i]=p;elsepre->right=p;p->right=pa; pre=p;if(NULL==M.chead[p->j]){ // 进行列插入M.chead[p->j]=p; p->down=NULL;}else{p->down=hl[p->j]->down; hl[p->j]->down=p;}hl[p->j]=p;pb=pb->right;}elseif((NULL!=pa)&&pa->j<pb->j){ // 如果此时的pb元素因该放在pa后面,则取以后的pa再来比较pre=pa; pa=pa->right;}elseif(pa->j==pb->j){ // 如果pa,pb位于同一个位置上,则将值相加pa->e += pb->e;if(!pa->e){ // 如果相加后的和为0,则删除此节点,同时改变此元素坐在行,列的前驱元素的相应值if(NULL==pre) // 修改行前驱元素值M.rhead[pa->i]=pa->right;elsepre->right=pa->right;p=pa; pa=pa->right;if(M.chead[p->j]==p) M.chead[p->j]=hl[p->j]=p->down; // 修改列前驱元素值elsehl[p->j]->down=p->down;free(p); pb=pb->right;}else{pa=pa->right; pb=pb->right;}}}}OutPutSMatrix_OL(M);return true;}int main(){cout.fill('*');cout<<setw(80)<<'*';cout.fill(' ');// system("color 0C");cout<<setw(50)<<"***欢迎使用矩阵运算程序***"<<endl; //输出头菜单cout.fill('*');cout<<setw(80)<<'*';cout.fill(' ');cout<<"请选择要进行的操作:"<<endl;cout<<"1:矩阵的转置。
c语言稀疏矩阵应用代码实现三元组,十字链表下的稀疏矩阵的加、转、乘的实现。
c语言稀疏矩阵应用代码实现三元组,十字链表下的稀疏矩阵的加、转、乘的实现。
在C语言中,实现稀疏矩阵的加法、转置和乘法涉及复杂的数据结构和算法。
其中,常用的表示稀疏矩阵的两种数据结构是三元组和十字链表。
下面我将为您提供一个简单的示例代码,用C语言实现稀疏矩阵的加法、转置和乘法操作,使用三元组表示法来表示稀疏矩阵。
首先,我们需要定义表示稀疏矩阵的三元组结构体:```c#include<stdio.h>#define MAX_SIZE100typedef struct{int row;int col;int value;}Element;typedef struct{int rows;int cols;int num_elements;Element data[MAX_SIZE];}SparseMatrix;```接下来,我们实现稀疏矩阵的加法、转置和乘法函数:```c#include<stdbool.h>//加法函数SparseMatrix addSparseMatrix(SparseMatrix matrix1,SparseMatrix matrix2){ SparseMatrix result;result.rows=matrix1.rows;result.cols=matrix1.cols;result.num_elements=0;int i=0,j=0;while(i<matrix1.num_elements&&j<matrix2.num_elements){if(matrix1.data[i].row<matrix2.data[j].row||(matrix1.data[i].row==matrix2.data[j].row&&matrix1.data[i].col<matrix2.data[j].col)){ result.data[result.num_elements++]=matrix1.data[i++];}else if(matrix1.data[i].row>matrix2.data[j].row||(matrix1.data[i].row==matrix2.data[j].row&&matrix1.data[i].col>matrix2.data[j].col)){ result.data[result.num_elements++]=matrix2.data[j++];}else{Element element;element.row=matrix1.data[i].row;element.col=matrix1.data[i].col;element.value=matrix1.data[i].value+matrix2.data[j].value;if(element.value!=0){result.data[result.num_elements++]=element;}i++;j++;}}while(i<matrix1.num_elements){result.data[result.num_elements++]=matrix1.data[i++];}while(j<matrix2.num_elements){result.data[result.num_elements++]=matrix2.data[j++];}return result;}//转置函数SparseMatrix transposeSparseMatrix(SparseMatrix matrix){ SparseMatrix result;result.rows=matrix.cols;result.cols=matrix.rows;result.num_elements=matrix.num_elements;int count[matrix.cols];int index[matrix.cols];for(int i=0;i<matrix.cols;i++){count[i]=0;}for(int i=0;i<matrix.num_elements;i++){count[matrix.data[i].col]++;}index[0]=0;for(int i=1;i<matrix.cols;i++){index[i]=index[i-1]+count[i-1];}for(int i=0;i<matrix.num_elements;i++){int j=index[matrix.data[i].col];result.data[j].row=matrix.data[i].col;result.data[j].col=matrix.data[i].row;result.data[j].value=matrix.data[i].value;index[matrix.data[i].col]++;}return result;}//乘法函数SparseMatrix multiplySparseMatrix(SparseMatrix matrix1,SparseMatrix matrix2){ SparseMatrix result;if(matrix1.cols!=matrix2.rows){result.rows=0;result.cols=0;result.num_elements=0;return result;}result.rows=matrix1.rows;result.cols=matrix2.cols;result.num_elements=0;bool visited[matrix2.cols];for(int i=0;i<matrix2.cols;i++){visited[i]=false;}for(int i=0;i<matrix1.num_elements;i++){for(int j=0;j<matrix2.num_elements;j++){if(matrix1.data[i].col==matrix2.data[j].row){Element element;element.row=matrix1.data[i].row;element.col=matrix2.data[j].col;element.value=matrix1.data[i].value*matrix2.data[j].value; result.data[result.num_elements++]=element;visited[matrix2.data[j].col]=true;}}}for(int i=0;i<matrix2.cols;i++){if(!visited[i]){for(int j=0;j<matrix1.rows;j++){Element element;element.row=j;element.col=i;element.value=0;result.data[result.num_elements++]=element;}}}return result;}```请注意,上述代码只是一个简单示例,实际应用中可能需要根据具体需求进行优化和扩展。
三元组矩阵乘法
三元组矩阵乘法
三元组矩阵乘法是指对两个稀疏矩阵进行乘法运算的一种方法。
稀疏
矩阵是指大部分元素为零的矩阵。
三元组是一种表示稀疏矩阵的数据
结构,它使用三个列表来存储非零元素的行、列和值。
三元组矩阵乘法的步骤如下:
1. 将两个稀疏矩阵转换为三元组表示法。
2. 遍历第一个矩阵的行,对于每一行,遍历第二个矩阵的列。
3. 在每次遍历中,将第一个矩阵当前行的非零元素与第二个矩阵当前
列的非零元素进行乘法运算,并将结果累加到最终结果的对应位置上。
4. 返回最终结果的三元组表示。
三元组矩阵乘法的优点是,由于只计算非零元素的乘积,可以减少不
必要的运算,提高运算效率。
同时,三元组表示法可以更有效地存储
和处理稀疏矩阵,节省存储空间和提高运算速度。
需要注意的是,三元组矩阵乘法适用于稀疏矩阵的乘法运算,对于密
集矩阵,传统的矩阵乘法算法更适合。
稀疏矩阵相乘三元组
稀疏矩阵相乘(三元组)# include <stdio.h># include <stdlib.h># define NULL 0# define OK 1# define ERROR 0# define MAXSIZE 100 /* 矩阵中非零元的最大值*/# define MAXRC 10 /* 矩阵的最大行值*/typedef int status ;/********** 稀疏矩阵的行逻辑链接的顺序表存储表示**********/typedef struct /* 非零元的三元组*/{int i, j ; /* 非零元的行下标和列下标*/int e ;}Triple;typedef struct /* 稀疏矩阵的行逻辑链接的顺序表*/{Triple data[MAXSIZE+1]; /* 非零三元组表,data[0]未用,以下定义的数组都是从1开始*/int rpos[MAXRC+1]; /* 代表各行第一个非零元的序号表,其值为data的下标*/int mu,nu,tu; /* 矩阵的行数、列数、非零元的个数*/}RLSMatrix; /* R:row L:logic S:sequence *//********* 基本操作的函数原型的声明*********/status CreateSMatrix_RL(RLSMatrix *matrix);// 创建一个稀疏矩阵;// 输入行数、列数,支持乱序输入三元组,并计数;// 以行为主序进行重新排列,并记录每行起始位置于matrix->rpos[row];// 若非零元超过MAXSIZE或行数超过MAXRC,则返回ERROR,否则OK;void PrintSMatrix_RL(RLSMatrix *matrix);// 输入矩阵,打印出矩阵的行数、列数、非零元个数,以及整个矩阵;status MultSMatrix_RL(RLSMatrix *M,RLSMatrix *N,RLSMatrix * Q);// 输入两个稀疏矩阵M和N,并初始化Q,然后计算M*N的值赋给Q;// 如果M->mu!=N->nu或列数大于MAXRC或者计算出的非零元个数大于MAXSIZE,都返回ERROR,否则OK;// 计算过程如下:// 1. 由于矩阵M和Q的行数相等并且C语言以行为主序进行存储,所以以M 进行逐行的扫描。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
储 所 以 可 以 采 用 固 定 三 元 组 表 a 中 的 元 素 ( i , k , Mik )
(1≤i≤m1,1≤k≤n1),在三元组表b中找所有行号为k的的对 应元素(k,j, Nkj)(1≤k≤m2,1≤j≤n2)进行相乘、 累加, 从而得到Q[i][j],即以三元组表a中的元素为基准, 依次 求出其与三元组表b的有效乘积。
0 Q 1 0
6 0 4
图5.17 Q=M×N
第十二讲
图5.18 矩阵M、N、Q的三元组表
第十二讲
经典算法中,不论M[i][k]、N[k][j]是否为零,
都要进行一次乘法运算,而实际上,这是没有必要的。采用三
元组表的方法来实现时,因为三元组只对矩阵的非零元素做存
· B=(A, A, D) 长度为3的广义表, 其前两个元素 为表A, 第三个元素为空表D。
· C=(a,C) 长度为2递归定义的广义表,C相当于无 穷表C=(a,(a,(a,(…))))。 #其中,A、B、C、D是广义表的名字。 下面以广义表A为例, 说明求表头、 表尾的操作: head(A)=a 表A的表头是a。 表A的表尾是((b, c))。
第十二讲
#define MAXSIZE 1000 /*非零元素的个数最多为1000*/ #define MAXROW 1000 /*矩阵最大行数为1000*/ typedef struct { int row, col; /*该非零元素的行下标和列下标*/ ElementType e; /*该非零元素的值*/ }Triple; typedef struct { Triple data[MAXSIZE+1]; /* 非零元素的三元组表,data[0]未用*/ int first[MAXROW+1]; /* 三元组表中各行第一个非零元素所在的 位置 */ int m, n, len;/*矩阵的行数、 列数和非零元素的个数*/ }TriSparMatrix;
第十二讲
else { /* 寻找行表中的插入位置 */ for(q=M->row_head[i]; q->right&&q->right->col<j; q=q->right) } if(M->col_head[j]==NULL) M->col_head[j]=p; else { /*寻找列表中的插入位置*/ p->right=q->right; q->right=p; /* 完成插入 */
0 1 Q 0 0 0
0 6 21 3 0 0 0 0 0 8 0 1 0 0 0 0 0 0 6 0
图5.19 Q=M×N
第十二讲
Row Num[row]
1 2
2 1
3 1
4 1
(5)
First[row]
1
3
4
5
6
图5.20 图5.19中矩阵N对应的向量num[row], first[row]
第十二讲
算法中附设两个向量num[ ]、first[ ],其中num
[row]表示三元组表b中第row行非零元素个数(1≤row≤m2), first[row]表示三元组表b中第row行第一个非零元素所在的 位置。显然,first[row+1]-1指向三元组表b中第row行最后一 个非零元素的位置。 first[1]=1; first[row]=first[row-1]+num[row-1], 2≤row≤m2+1。 这里,first[m2+1]-1表示最后一行最后一个非零元素 的存储位置。当三元组表a中第i行非零元素的列号等于三元
OLink * row_head, *col_head; /* 行、 列链表的头指针向量 */
int m, n, len; /* 稀疏矩阵的行数、 列数、 非零元素的个数 */ }CrossList;
第十二讲
CreateCrossList (CrossList * M) {/* 采用十字链表存储结构, 创建稀疏矩阵M */ scanf(&m, &n, &t); /* 输入M的行数, 列数和非零元素的个数 */
第十二讲
用三元组表实现稀疏矩阵的乘法运算
第十二讲
两个矩阵相乘也是矩阵的一种常用的运算。设矩阵M是
m1×n1矩阵,N是m2×n2矩阵;若可以相乘,则必须满足矩
阵M的列数n1与矩阵N的行数m2相等,才能得到结果矩阵 Q=M×N(一个m1×n2的矩阵)。
数学中矩阵Q中的元素的计算方法如下:
Q[i ][ j ] M [i ][k ] N [k ][ j ]
是一个广义表,则称di是广义表GL的子表。在广义表GL中,d1
是广义表GL的表头,而广义表GL其余部分组成的表(d2 , d3,…,dn)称为广义表的表尾。由此可见广义表的定义是递归
定义的,因为在定义广义表时又使用了广义表的概念。
第十二讲
· D=()空表;其长度为零。 · A=(a, (b, c)) 表长度为2的广义表,其中第一个 元素是单个数据a,第二个元素是一个子表(b,c)。
k 1
n1
其中: 1≤i≤m1, 1≤j≤n2。
第十二讲
根据数学上矩阵相乘的原理, 我们可以得到矩阵相乘的 经典算法:
for(i=1; i<=m1; i++)
for(j=1; j<=n2; j++)
{Q[i][j]=0;
for(k=1; k<=n1; k++)
Q[i][j]=Q[i][j]+M[i][k]*N[k][j];
tail(A)=((b, c)) 广义表的表尾一定是一个表。
第十二讲
从上面的例子可以看出: (1) 广义表的元素可以是子表,而子表还可以是子表…… 由此可见,广义表是一个多层的结构。 (2) 广义表可以被其它广义表共享,如广义表B就共享 表A。 在表B中不必列出表A的内容,只要通过子表的名称就 可以引用该表。
第十二讲
typedef enum {ATOM, LIST} ElemTag; /* ATOM=0,表示原子;LIST=1, 表示子表 */ typedef struct GLNode
{
ElemTag tag; union /* 标志位tag用来区别原子结点和表结点 */
{
AtomType
矩阵不仅节约了空间,而且使得矩阵某些运算的运算时间比经
典算法还少。但是在进行矩阵加法、减法和乘法等运算时,有 时矩阵中的非零元素的位置和个数会发生很大的变化。如
A=A+B, 将矩阵B加到矩阵A上,此时若还用三元组表表示法,
势必会为了保持三元组表“以行序为主序”而大量移动元素。
第十二讲
在十字链表中,矩阵的每一个非零元素用一个结点表示,
(3) 广义表具有递归性, 如广义表C。
第十二讲
由于广义表GL=(d1,d2,d3,…,dn)中的数据元素既可 以是单个元素,也可以是子表,因此对于广义表来说,我们
难以用顺序存储结构来表示它,通常我们用链式存储结构来
表示。表中的每个元素可用一个结点来表示。广义表中有两 类结点:一类是单个元素结点;另一类是子表结点。 任何一 个非空的广义表都可以分解成表头和表尾两部分,反之,一 对确定的表头和表尾可以唯一地确定一个广义表。由此,一 个表结点可由三个域构成:标志域、指向表头的指针域和指 向表尾的指针域。而元素结点只需要两个域:标志域和值域。
M->row_head[ ]=M->col_head[ ]=NULL;
/* 初始化行、 列头指针向量, 各行、 列链表为空的链表 */ for(scanf(&i, &j, &e); i!=0; scanf(&i, &j, &e)) { if(!(p=(OLNode *) malloc(sizeof(OLNode)))) exit(OVERFLOW); p->row=i; p->col=j; p->value=e; /* 生成结点 */ if(M->row_head[i]==NULL) M->row_head[i]=p;
第十二讲
具体算法如下:
该算法的时间主要耗费在乘法运算及累加上,其时间复杂度为O (A.len×B.n)。当A.len 接近于A.m×A.n时,该算法时间复杂度接近于 经典算法的时间复杂度O(A.m×A.n×B.n)。
第十二讲
稀疏矩阵的链式存储结构: 十字链表
与用二维数组存储稀疏矩阵比较,用三元组表表示的稀疏
atom; /* 原子结点的值域atom */
struct { struct GLNode * hp, *tp; } htp;
/* 表结点的指针域htp, 包括表头指针域hp和表尾指针域tp */
} atom_htp; } *GList; /* atom_htp 是原子结点的值域atom和表结点的指针域htp的联合体域 */
LISP语言中,广义表是一种最基本的数据结构,就连LISP 语 言的程序也表示为一系列的广义表。
第十二讲
在第2章中, 线性表被定义为一个有限的序列(a1 ,a2 ,
a3,…,an), 其中ai被限定为是单个数据元素。广义表也是n个
数据元素(d1,d2,d3,…,dn )的有限序列,但不同的是,广 义表中的di既可以是单个元素,还可以是一个广义表,通常 记作: GL=(d1,d2,d3, …,dn)。GL是广义表的名字,通 常广义表的名字用大写字母表示。n是广义表的长度。若其中di
该结点除了(row,col,value)以外,还要有以下两个链域:
right: 用于链接同一行中的下一个非零元素; down: 用于链接同一列中的下一个非零元素。