稀疏矩阵的快速转置

一般的稀疏矩阵转置算法

void transpose(term* a, term *b)
{
	int n;
	int currentb;
	n = a[0].value;
	b[0].row = a[0].col;
	b[0].col = a[0].row;
	b[0].value = n;
	if (n > 0) //非零矩阵 
	{
		currentb = 1;
		for (int i = 0; i < a[0].col; ++i)
		{
			//按a的列转置 
			for (int j = 1; j <= n; ++j)
			{
				if (a[j].col == i)//当前列的所有元素 
				{
					b[currentb].row = a[j].col;
					b[currentb].col = a[j].row;
					b[currentb].value = a[j].value;
					++currentb;
				}
			}
		}
	}
	return;
}

这个算法的渐进时间复杂度为O(col*element)。

当这个矩阵元素达到col*row级别时;渐进时间复杂度为O(col^2*row),节省了空间的同时浪费了太多的时间。

对于三元组序列表示的矩阵,可以在O(cols + element)时间内将其转置,通过增加少许储存空间,获取更好的转置算法。如下

#include <stdio.h>
#define MAX_TERMS 101
typedef struct{
	int row = 0;
	int col = 0;
	int value = 0;
} term;
void initSparseMatrix(int c[][10])//为了方便,直接这样初始化了原始的稀疏矩阵 
{
	for (int i = 0; i < 10; ++i)
	{
		for (int j = 0; j < 8; ++j)
		{
			if(i == j + 1)
				c[i][j] = i * j + 1;
			else
				c[i][j] = 0;
		}
	}
	return;
}
void saveMatrixIntoArray(term* arr, int c[][10])//将稀疏矩阵储存到数组a中 
{
	int pos = 1;
	for (int i = 0; i < 10; ++i)
	{
		++arr[0].row;
		for (int j = 0; j < 8; ++j)
		{
			if (c[i][j] != 0)
			{
				arr[pos].row = i;
				arr[pos].col = j;
				arr[pos++].value = c[i][j];
				++arr[0].value;
			}
			if (arr[0].row == 1)
				++arr[0].col;
		}
	}
	return;
}
void transPose(term* arr, term* brr)//将a转置到b中储存 
{
	int row_nums = arr[0].row;
	int col_nums = arr[0].col;
	int num_terms = arr[0].value;
	int brow_terms[col_nums];
	int pos[col_nums];						//用pos数组储存每次转置时存放到b中元素应放的下标 
	brr[0].row = arr[0].col;
	brr[0].col = arr[0].row;
	brr[0].value = num_terms;
	if (num_terms > 0)
	{
		for (int i = 0; i < col_nums; ++i)//首先初始化b中每行元素的个数为0 
		{
			brow_terms[i] = 0;
		}
		for (int i = 1; i <= num_terms; ++i)//计算b中每行元素个数,即a中每列元素的个数 
		{
			++brow_terms[arr[i].col];
		}
		pos[0] = 1;
		for (int i = 1; i < col_nums; ++i)//计算每行开始转存时元素 的下标 
		{
			pos[i] = pos[i-1] + brow_terms[i-1];
		}
		int j;
		for (int i = 1; i <= num_terms; ++i)//将a中的元素转存到b中 
		{
			j = pos[arr[i].col]++;
			brr[j].row = arr[i].col;
			brr[j].col = arr[i].row;
			brr[j].value = arr[i].value;
		}
		return;
	}
}
void printArray(term* arr)//打印输出查看效果 
{
	int num_terms = arr[0].value;
	printf("this one:\n");
	for (int i  = 1; i <= num_terms; ++i)
	{
		printf("(%d,%d):%d\n",arr[i].row,arr[i].col,arr[i].value);
	}
	return;
}
int main()
{
	term a[MAX_TERMS];
	term b[MAX_TERMS];
	int  source[10][10];
	initSparseMatrix(source);
	saveMatrixIntoArray(a,source);
	transPose(a,b);
	printArray(a);
	printArray(b);
	return 0;
} 


简单来说,相比于第一个转置算法,快速转置的提升在于不用检索a中的每一个元素查找位于当前列的元素,并将其放置到b中。利用pos数组储存了b中每一行对应的起始下标,从而能够直接讲元素加入到b中。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值