数据结构 稀疏矩阵三元组顺序表 基本操作

【数据结构】稀疏矩阵 三元组顺序表存储 基本操作

1.稀疏矩阵定义:

假设在 mn 的矩阵中,又t个元素不为零。δ = t/mn ,称δ为矩阵的稀疏因子,通常定义δ小于等于0.05时称为稀疏矩阵。


2.三元组顺序表存储结构

矩阵中每个元素用三个量存储,位置ij 以及值e

typedef struct {
	int i, j; //三元组的行列值
	ElemType e; 
}Triple;

typedef struct {
	Triple data[MAXSIZE + 1]; //非零三元组表,data0未用
	int mu, nu, tu;			  //三元组行数,列数,非零元素值
}TSMatrix ;

3.基本操作

1.创建稀疏矩阵 M

Status CreateSMatrix(TSMatrix &M) {
	cout << "输入矩阵行数,列数,非零元素个数:" << endl;
	cin >> M.mu >> M.nu >> M.tu;
	cout << "依次输入" << M.tu << "个元素的行数,列数,元素值:" << endl;
	for (int i = 1; i <= M.tu; i++)
	{
		cin >> M.data[i].i >> M.data[i].j >> M.data[i].e;
	}
	cout << "矩阵构造完成" << endl;
	return OK;
}

2.输出稀疏矩阵M

Status PrintSMatrix(TSMatrix M) {
	//打印稀疏矩阵M
	cout << "矩阵的函数行数,列数,非零元素个数为: " << M.mu << "  " << M.nu << "  " << M.tu << endl;
	cout << "矩阵中非零元素为:"<<endl;
	for (int i = 1; i <= M.tu; i++)
	{
		cout << "(" << M.data[i].i << "," << M.data[i].j<< ',' << M.data[i].e << ')' << endl;
	}
	return OK;
}

3.稀疏矩阵求和
算法思路:
依次取两个矩阵中的元素,首先比较行数mumu不一致则直接存入mu小的元素,并取下一个元素。若mu一致则比较列数nu,进行同样操作。
当两个元素的munu都相等时,将元素值求和,若不为零,则存入元素,并取下两个元素比较。若和为零,直接取下两个元素比较,不进行存储。
进过while循环后,两个矩阵中会有一个矩阵元素有剩余,将其复制到新矩阵,便完成了矩阵加法。

Status AddSMatrix(TSMatrix M, TSMatrix N, TSMatrix &Q) {
	if (M.mu != N.mu || M.nu != N.nu)return ERROR;
	Q.mu = M.mu;
	Q.nu = M.nu;
	Q.tu = 0;
	int mtu=1, ntu=1;
	while (mtu<=M.tu && ntu<=N.tu)
	{
		if (M.data[mtu].i < N.data[ntu].i) {
			Q.data[++Q.tu] = M.data[mtu++];
		}
		else if (M.data[mtu].i > N.data[ntu].i) {
			Q.data[++Q.tu] = N.data[ntu++];
		}
		else {
			if (M.data[mtu].j < N.data[ntu].j) {
				Q.data[++Q.tu] = M.data[mtu++];
			}
			else if (M.data[mtu].j > N.data[ntu].j) {
				Q.data[++Q.tu] = N.data[ntu++];
			}
			else
			{
				if (M.data[mtu].e + N.data[ntu].e == 0) { ++mtu; ++ntu; }
				else
				{
					Q.data[++Q.tu] = M.data[mtu++];
					Q.data[Q.tu].e += N.data[ntu++].e;
				}
			}
		}
	}
	for ( ;  mtu<= M.tu; mtu++)
	{
		Q.data[++Q.tu] = M.data[mtu];
	}
	for (; ntu <= M.tu; ntu++)
	{
		Q.data[++Q.tu] = N.data[ntu];
	}
	return OK;
}

4.稀疏矩阵减法
减法相对于 M+(-N),与加法思路一致。

Status SubMatrix(TSMatrix M,TSMatrix N, TSMatrix &Q) {
	// M - N = M+(-N)
	for (int i = 1; i <= N.tu; i++)
	{
		N.data[i].e *= -1;
	}
	AddSMatrix(M, N, Q);
	return OK;
}

5.稀疏矩阵转置
一般转置方法:
基本思路:
依次找到M中每一列的所有元素,进行转置,这样得到的转置矩阵就是以行为主序进行排列

Status TransposeSMatrix(TSMatrix M, TSMatrix &T) {
	//三元组组存储表示,求系数矩阵M的转置矩阵T
	T.mu = M.mu; T.nu = M.mu; T.tu = M.tu;
	if (T.tu) {
		int q = 1;
		for(int col = 1;col<=M.nu;++col)
			for(int p=1;p<=M.tu;++p)
				if (M.data[p].j ==col)
				{
					T.data[q].i = M.data[p].j; T.data[q].j = M.data[p].i;
					T.data[q].e = M.data[p].e; ++q;
				}
	}
	return OK;
}
//算法分析:第一层循环是对矩阵M的列进行,第二层循环对所有元素进行,目的是使转置
//后的矩阵按照行为主序进行排列;算法时间复杂度为O(nu*tu),一般矩阵转置操作
//算法时间复杂度为O(nu*mu)

快速转置方法:
//新增两个向量,num,cpot
//num[col]表示矩阵M中第col列中非零元素个数
//cpot[col]指示M中第col列第一个非零元在b.data 中的位置。
//cpot[1]=1;
//cpot[col] = cpot[col-1] + num[col-1] 这一列第一个非零元位置等于上一列位置+元素个数

Status FastTransposeSMatrix(TSMatrix M, TSMatrix &T) {
	T.mu = M.mu; T.nu = M.nu; T.tu = M.tu;
	int* num=(int*)malloc(M.nu*sizeof(int));
	int* cpot=(int*)malloc(M.nu * sizeof(int));
	int col;
	int q;
	if (T.tu) {
		for (int col = 1; col <= M.nu; ++col) num[col] = 0;
		for (int t = 1; t <= M.tu; ++t) ++num[M.data[t].j];//求M中每一列含非零元个数
		cpot[1] = 1;
		//求第col列中第一个非零元在b.data 中的序号
		for ( col = 2; col <= M.nu; ++col)cpot[col] = cpot[col - 1] + num[col - 1];
		for (int p = 1; p <= M.tu; ++p) {
			col = M.data[p].j; q = cpot[col];
			T.data[q].i = M.data[p].j; T.data[q].j = M.data[p].i;
			T.data[q].e = M.data[p].e; ++cpot[col];
		}
	}
	return OK;
}
//代码分析:首先对矩阵M进行遍历,得到 num 向量
//通过cpot与num之间关系,得到 cpot 向量
//再次对M所有元素遍历,通过cpot向量找到该元素在 矩阵T中的位置
//++cpot[col];该列的第一个非零元素已经转换完毕,该列下一个元素位置应该在该元素之后

测试部分:

int main() {
	TSMatrix M, N, Q, T;
	CreateSMatrix(M);
	PrintSMatrix(M);
	CreateSMatrix(N);
	AddSMatrix(M, N, Q);
	cout << "加法运算完成:" << endl;
	PrintSMatrix(Q);
	TransposeSMatrix(Q, T);
	cout << "矩阵转置完成:" << endl;
	PrintSMatrix(T);
}

数据结构 稀疏矩阵三元组顺序表 基本操作_第1张图片

你可能感兴趣的:(数据结构严蔚敏)