稀疏矩阵问题

三元组表基础

	一般用三元组表来表示稀疏矩阵,定义如下:
typedef struct
{
	int row;//行号
	int col;//列号
	int d;//元素值
}TupNode;
typedef struct
{
	int rows;//行数
	int cols;//列数
	int nums;//非零元素个数
	TupNode data[10000];//数据域
}TSMatrix;
``

稀疏矩阵的旋转

稀疏矩阵相加最经典的就是直接让两个矩阵行列对换,但是这种算法时间空间复杂度都比较高,这里记录一次定位快速转置法:

void exchange(TSMatrix A, TSMatrix *B)
{
	int num[10000], position[10000];
	int col, t, p, q;
	if (B->nums > 0)
	{
	for (col = 1; col <= A.cols; col++)
		{
			num[col] = 0;
		}
		for (t = 1; t <= A.nums; t++)
		{
			num[A.data[t].col]++;
		}
		position[1] = 1;
		for (col = 2; col <= A.cols; col++)
		{
			position[col] = position[col - 1] + num[col - 1];//核心计算
		}
		for (p = 1; p <= A.nums; p++)
		{
			col = A.data[p].col;	q = position[col];
			B->data[q].row = A.data[p].col;
			B->data[q].col = A.data[p].row;
			B->data[q].d = A.data[p].d;
			position[col]++;//指向下一个列号为col的非零元素在三元组表
			B中的存放位置
		}
	}
}

这个算法核心在要记录两个数据:
1.待转置三元表组A中每一列的非零元素总个数,即转置后矩阵三元表组B的每一行中非零元素总个数
2.待转置矩阵A每一列中第一个非零元素在三元表组B中的位置,即转置后矩阵每一行中第一个非零元素在表B中的位置
为此设立两个数组num[],position[]来记录,如上述代码
主函数如下:

int c, r;
	int temp;
	cin >> c >> r;//c是行,r是列
	TSMatrix A, B;
	A.nums = 1; B.nums = 1;
	A.rows = c;	A.cols = r;	B.cols = c;	B.rows = r;
	for (int i = 1; i <= c; i++)//输入稀疏矩阵并转换成三元组表的形式
	{
		for (int j = 1; j <= r; j++)
		{
			cin >> temp;
			if (temp != 0)
			{
				A.data[A.nums].row = i;
				A.data[A.nums].col = j;
				A.data[A.nums].d = temp;
				A.nums++;
			}
		}
	}
	A.nums--;
	B.nums = A.nums;
	exchange(A, &B);
	int k  =0;
	for (int i = 1; i <= r; i++)
	{
		for (int j = 1; j <= c; j++)
		{
			if (B.data[k].row == i && B.data[k].col == j)
			{
				cout << B.data[k].d << " ";
				k++;
			}
			else
			{
				cout << "0" << " ";
			}
		}
		cout << endl;
	}

稀疏矩阵的相加

比起上面的旋转,矩阵相加就容易的多,但是要注意合并完后排序。排序要先按列序排,再按行序排,这样能输出正确的结果。
先附上题目:
【问题描述】

以三元组表存储的稀疏矩阵A、B非零元个数分别为m和n。试编写程序,完成A+B。

【输入形式】

第一排为分别为A、B元素的个数,以下各排分别输入对应的三元组,头m组为A中的元素,接下来为B的元素,同一个矩阵的元素按照行递增排列,第一行规定为1,同一行的元素按照列递增排列,第一列规定为1

【输出形式】

为相应的三元组,以回车分开,如果结果全部为0,则输出 -1 -1 -1

【样例输入】

2 1

1 2 3

1 3 4

1 3 3

【样例输出】

1 2 3

1 3 7

int main()
{
	int m, n;
	int a, b, c;
	TSMatrix A, B;
	A.nums = 0; B.nums = 0;
	cin >> m >> n;
	for (int i = 0; i < m; i++)
	{
		cin >> a >> b >> c;
		A.nums++;//三元组表从1开始存储数据
		A.data[A.nums].row = a;
		A.data[A.nums].col = b;
		A.data[A.nums].d = c;
	}
	for (int i = 0; i < n; i++)
	{
		cin >> a >> b >> c;
		B.nums++;
		B.data[B.nums].row = a;
		B.data[B.nums].col = b;
		B.data[B.nums].d = c;
	}
	for (int i = 1; i <= A.nums; i++)
	{
		for (int j = 1; j <= B.nums; j++)
		{
			if (A.data[i].row == B.data[j].row && A.data[i].col == B.data[j].col)
			{
				A.data[i].d = A.data[i].d + B.data[j].d;
				for (int r = j; r <= B.nums; r++)//覆盖
				{
					B.data[r] = B.data[r + 1];
					B.nums--;
				}
			}
		}
	}
	for (int i = 1; i <= B.nums; i++)//连接B表到A表末尾
	{
		A.nums++;
		A.data[A.nums] = B.data[i];
	}
	for (int j = 1; j <= A.nums; j++)
	{
		TupNode temp;
		for (int i = 1; i <= A.nums-j; i++)
		{
			if (A.data[i].col > A.data[i + 1].col)
			{
				temp = A.data[i];
				A.data[i] = A.data[i + 1];
				A.data[i + 1] = temp;
			}
		}
	}
	for (int j = 1; j <= A.nums; j++)
	{
		TupNode temp;
		for (int i = 1; i <= A.nums-j; i++)
		{
			if (A.data[i].row > A.data[i + 1].row)
			{
				temp = A.data[i];
				A.data[i] = A.data[i + 1];
				A.data[i + 1] = temp;
			}
		}
	}
	int t = 0;
	for (int i = 1; i <= A.nums; i++)
	{
		if (A.data[i].d!=0)
		{
			cout << A.data[i].row <<" "<< A.data[i].col<<" " << A.data[i].d << endl;
		}
		else
		{
			t++;
		}
	}
	if (t == A.nums)
	{
		cout << "-1 -1 -1";
	}
}

我的思路是先查找两个表中能合并的元素,合并之后就在B表中覆盖掉这个元素。
然后将两个表合并,再排序,最后输出。
这种写法不需要脑子,但是很复杂,要注意等号是否能取到。
用sort函数会简明很多。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个用C++解决稀疏矩阵问题的示例代码: ``` #include <iostream> using namespace std; class SparseMatrix { private: int row, column, count; int *rpos, *cpos, *values; public: SparseMatrix(int r, int c, int cnt) : row(r), column(c), count(cnt) { rpos = new int[count]; cpos = new int[count]; values = new int[count]; } ~SparseMatrix() { delete[] rpos; delete[] cpos; delete[] values; } void Set(int r, int c, int v) { if (r < 0 || r >= row) return; if (c < 0 || c >= column) return; int i = 0, j = count - 1, k = -1; while (i <= j) { int mid = (i + j) / 2; if (rpos[mid] == r && cpos[mid] == c) { k = mid; break; } if (rpos[mid] < r || (rpos[mid] == r && cpos[mid] < c)) { i = mid + 1; } else { j = mid - 1; } } if (k == -1 && v == 0) return; if (k != -1 && v == 0) { for (int i = k; i < count - 1; i++) { rpos[i] = rpos[i + 1]; cpos[i] = cpos[i + 1]; values[i] = values[i + 1]; } count--; return; } if (k == -1) { if (count == 0) { rpos[0] = r; cpos[0] = c; values[0] = v; count = 1; } else { int p = count; for (int i = 0; i < count; i++) { if (rpos[i] > r || (rpos[i] == r && cpos[i] > c)) { p = i; break; } } for (int i = count; i > p; i--) { rpos[i] = rpos[i - 1]; cpos[i] = cpos[i - 1]; values[i] = values[i - 1]; } rpos[p] = r; cpos[p] = c; values[p] = v; count++; } } else { values[k] = v; } } int Get(int r, int c) { if (r < 0 || r >= row) return 0; if (c < 0 || c >= column) return 0; int i = 0, j = count - 1; while (i <= j) { int mid = (i + j) / 2; if (rpos[mid] == r && cpos[mid] == c) { return values[mid]; } if (rpos[mid] < r || (rpos[mid] == r && cpos[mid] < c)) { i = mid + 1; } else { j = mid - 1; } } return 0; } }; int main() { SparseMatrix m(3, 4, 4); m.Set(0, 1, 2); m.Set(1, 2, 3); m.Set(2, 3, 4); m.Set(0, 1, 0); m.Set(1, 2, 0); m.Set(2, 3, 0); cout << m.Get(0, 0) << endl; cout << m.Get(0, 1) << endl; cout << m.Get(1, 2) << endl; cout << m.Get(2, 3) << endl; return 0; } ``` 示例代码中定义了一个 SparseMatrix 类用于表示稀疏矩阵,通过 Set() 方法设置矩阵元素的值,通过 Get() 方法获取矩阵元素的值,主函数中给出了一个示例用法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值