欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

数据结构实现稀疏矩阵(采用三元组表示)的基本运算

程序员文章站 2022-07-12 09:53:21
...

数据结构实现稀疏矩阵(采用三元组表示)的基本运算

目的

领会稀疏矩阵三元组存储结构及基本算计运算

内容

假设n*n的稀疏矩阵A采用三元组表示,设计一个程序实现以下功能

  1. 生成以下两个稀疏矩阵的三元组a和b
  2. 输出a转置矩阵的三元组
  3. 输出a+b的三元组
  4. 输出a*b的三元组

源代码(经VS、decC++编译通过)

#include <stdio.h>
#include <stdbool.h>
#include<stdlib.h>

#define N 4
#define MAX_SIZE 100 // 矩阵中非零元素最多个数

typedef int ElemType;

/*
在矩阵中,若数值为0的元素数目远远多于非0元素的数目,并且非0元素分布没有规律时,则称该矩阵为稀疏矩阵;
与之相反,若非0元素数目占大多数时,则称该矩阵为稠密矩阵。
*/

/*三元组定义*/
typedef struct
{
	int r; /*行号*/
	int c; /*列号*/
	ElemType d; /*元素值*/
}TupNode; 

 /*三元组存储结构顺序表定义*/
typedef struct
{
	int rows; // 行数值
	int cols; // 列数值
	int nums; // 非零元素个数
	TupNode data[MAX_SIZE];
}TSMatrix; 


/*产生稀疏矩阵A的三元组的顺序表存储结构t*/
static void create_matrix(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.nums].c = j; /*列号*/
				t.data[t.nums].d = A[i][j]; /*元素值*/
				t.nums++; /*非零元素个数增1*/
			}
		}
	}
}

/*输出三元组表示t*/
static void disp_matrix(TSMatrix t)
{
	int i;

	/*异常打回*/
	if (t.nums <= 0)
		return;

	/*行列数与非零个数输出*/
	printf("\t行号、列号、与非零值\n");
	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);
}

/*------------------------求三元组表示t的转置矩阵tb----------------------*/
/**
*   转置矩阵:
*       把矩阵A的行换成相应的列,得到的新矩阵称为A的转置矩阵。
*/
static void tran_matrix(TSMatrix t, TSMatrix &tb)
{
	int p, v;
	int q = 0; // q为tb.data的下标

	tb.rows = t.cols; // 转置矩阵行数值
	tb.cols = t.rows; // 转置矩阵列数值
	tb.nums = t.nums; // 转置矩阵非零元素个数
	if (t.nums != 0)
	{
		for (v = 0; v < t.cols; v++) // tb.data[q]中的记录以c域的次序排列
		{
			for (p = 0; p < t.nums; p++) // p为t.data的下标
			{
				if (t.data[p].c == v)
				{
					tb.data[q].r = t.data[p].c; // 转置矩阵的行号
					tb.data[q].c = t.data[p].r; // 转置矩阵的列号
					tb.data[q].d = t.data[p].d; // 转置矩阵的元素值
					q++;
				}
			}
		}
	}
}

/*------------------------求c=a+b----------------------*/
static bool matrix_add(TSMatrix a, TSMatrix b, TSMatrix &c) // 引用类型形参c
{
	int i = 0; // a中非零元素个数索引
	int j = 0; // b中非零元素个数索引
	int k = 0; // c中非零元素个数
	ElemType v;

	if (a.rows != b.rows || a.cols != b.cols) // 行数或列数不等时不能进行相加运算
		return false;
	// c的行列数与a的相同
	c.rows = a.rows;
	c.cols = a.cols;
	while (i < a.nums && j < b.nums) // 处理a和b中的元素(假设 a.nums = 6, b.nums = 4)
	{
		if (a.data[i].r == b.data[j].r) // a元素的行号等于b元素的行号
		{
			if (a.data[i].c < b.data[j].c) // a元素的列号小于b元素的列号
			{
				// 将a元素添加到c中
				c.data[k].r = a.data[i].r;
				c.data[k].c = a.data[i].c;
				c.data[k].d = a.data[i].d;
				k++;
				i++;
			}
			else if (a.data[i].c > b.data[j].c) // a元素的列号大于b元素的列号
			{
				// 将b元素添加到c中
				c.data[k].r = b.data[j].r;
				c.data[k].c = b.data[j].c;
				c.data[k].d = b.data[j].d;
				k++;
				j++;
			}
			else // a元素的列号等于b元素的列号
			{
				v = a.data[i].d + b.data[j].d;
				if (v != 0) // 只将不为0的结果添加到c中
				{
					c.data[k].r = a.data[i].r;
					c.data[k].c = a.data[i].c;
					c.data[k].d = v;
					k++;
				}
				i++;
				j++;
			}
		}
		else if (a.data[i].r < b.data[j].r) // a元素的行号小于b元素的行号
		{
			// 将a元素添加到c中
			c.data[k].r = a.data[i].r;
			c.data[k].c = a.data[i].c;
			c.data[k].d = a.data[i].d;
			k++;
			i++;
		}
		else // a元素的行号大于b元素的行号
		{
			// 将b元素添加到c中
			c.data[k].r = b.data[j].r;
			c.data[k].c = b.data[j].c;
			c.data[k].d = b.data[j].d;
			k++;
			j++;
		}
		c.nums = k;
	}

	return true;
}

/*------------------------返回三元组t表示的A[i][j]值----------------------*/
static int get_value(TSMatrix t, int i, int j)
{
	int k = 0;

	while (k < t.nums && (t.data[k].r != i || t.data[k].c != j))
		k++;
	if (k < t.nums)
		return t.data[k].d;
	else
		return 0;
}

/*------------------------求c=a*b----------------------*/
static bool matrix_mul(TSMatrix a, TSMatrix b, TSMatrix &c) // 引用类型形参c
{
	int i;
	int j;
	int k;
	int p = 0; // 矩阵c的非零元素个数
	ElemType s;

	if (a.cols != b.rows) // a的列数不等于b的行数时不能进行乘法运算
		return false;
	for (i = 0; i < a.rows; i++) // 矩阵c的行数
	{
		for (j = 0; j < b.cols; j++) // 矩阵c的列数
		{
			s = 0;
			for (k = 0; k < a.cols; k++)
			{
				s = s + get_value(a, i, k) * get_value(b, k, j); // 求三元组元素
			}
			if (s != 0) // 产生一个三元组元素
			{
				c.data[p].r = i; // 三元组元素的行号
				c.data[p].c = j; // 三元组元素的列号
				c.data[p].d = s; // 三元组元素的元素值
				p++;
			}
		}
	}

	c.rows = a.rows;
	c.cols = b.cols;
	c.nums = p; // 矩阵c的非零元素个数

	return true;
}

int main(void)

{
	/*生成稀疏矩阵三元组a*/
	ElemType a1[N][N] = {
		{ 1, 0, 3, 0 },
		{ 0, 1, 0, 0 },
		{ 0, 0, 1, 0 },
		{ 0, 0, 1, 1 }
	};
	/*生成稀疏矩阵三元组b*/
	ElemType b1[N][N] = {
		{ 3, 0, 0, 0 },
		{ 0, 4, 0, 0 },
		{ 0, 0, 1, 0 },
		{ 0, 0, 0, 2 }
	};

	/*定义三元组顺序表*/
	TSMatrix a, b, c;

	/*产生稀疏矩阵A的三元组存储结构t*/

	create_matrix(a, a1);
	printf("**********产生稀疏矩阵A的三元组存储结构t执行完毕***********\n");

	printf("**********输出三元组:非零个数行号、列号、元素值***********\n");
	disp_matrix(a);

	/*产生稀疏矩阵B的三元组存储结构t*/
	create_matrix(b, b1);
	printf("**********产生稀疏矩阵B的三元组存储结构t执行完毕***********\n");

	printf("**********输出三元组:非零个数行号、列号、元素值***********\n");
	disp_matrix(b);

	/*将A三元组转置为C*/
	tran_matrix(a, c);
	printf("**********三元组a转置为三元组c执行完毕***********\n");


	printf("c的三元组:\n");
	disp_matrix(c);

	/*三元组a+b-->c*/
	printf("*********相加三元组a和b********\n");
	matrix_add(a, b, c);
	printf("*********相加三元组a和b执行完毕********\n");

	printf("c的三元组:\n");
	disp_matrix(c);


	printf("*********相乘三元组a和b********\n");
	matrix_mul(a, b, c);
	printf("*********相乘三元组a和b执行完毕********\n");
	printf("c的三元组:\n");
	disp_matrix(c);

	system("pause");
}