【数据结构之旅】稀疏矩阵的快速转置

说明:

稀疏矩阵的快速转置算法的核心在于,用一个数组num记录原来矩阵中的每列非零元个数,用另一个数组cpos来记录原矩阵每列第一个非零元在新矩阵中的位置,以此来达到快速转置的目的。

用这样的方法,主要是希望,矩阵转置后,存储顺序依然是按照行来存储的。



1.实现及代码注释

根据上面的核心提示,可以有如下的代码,下面的代码中的注释已经非常详细,因此这里就不把每一部分实现的功能独立开来了:

#include<stdio.h>
#include<stdlib.h>
#define OVERFLOW -1
#define OK 1
#define ERROR 0
#define TRUE 2
#define FALSE -2

typedef int ElemType;
typedef int Status;

typedef struct{ //非零元三元组类型结构体 
	int i, j;	//非零元的行和列 
	ElemType e;	//非零元的值 
} Triple;		//非零元三元组类型结构体定义关键字

typedef struct{		//矩阵类型结构体 
	Triple *data;	//data域,指向非零元三元组的结构体指针 
	int mu, nu, tu;	//矩阵的行数、列数和非零元个数 
} TSMatrix;			//矩阵类型结构体定义关键字

 /*
 	0	14	0	0	-5
 	0	-7	0	0	0
 	36	0	0	28	0
 
 	mu = 3; nu = 5; tu = 5
*/

Status CreateSMatrix(TSMatrix &M){	//创建一个稀疏矩阵 
	M.tu = 5;

	M.data = (Triple*)malloc(sizeof(Triple) * (M.tu + 1)); //data域存储元素的大小比稀疏矩阵的非零元个数大1,是因为data[0]不使用 
	if(NULL == M.data)
		return OVERFLOW;
	M.data[1].i = 1;
	M.data[1].j = 2;
	M.data[1].e = 14;

	M.data[2].i = 1;
	M.data[2].j = 5;
	M.data[2].e = -5;

	M.data[3].i = 2;
	M.data[3].j = 2;
	M.data[3].e = -7;

	M.data[4].i = 3;
	M.data[4].j = 1;
	M.data[4].e = 36;

	M.data[5].i = 3;
	M.data[5].j = 4;
	M.data[5].e = 28;

	M.mu = 3;
	M.nu = 5;

	return OK;
}

Status FastTransposeSMatrix(TSMatrix M, TSMatrix &T){ //采用顺序表存储表示,求稀疏矩阵M的转置矩阵T 
	int j, p, q, t;
	/*j记录遍历时的当前列,cops[j],则表示当前列第一个非零元的位置或者该列非零元位置的其它位置(cops[j]++),正式转置时用; 
	p记录遍历时的非零元个数,正式转置时用; 
	q记录cops[j],简化代码的表示,正式转置时用 ;
	t用在转置准备时。 
	*/
	int *num;	//保存每一列的非零元个数 
	int *cpos;	//保存转置后每列第一个非零元在T中所处的序号
				//cops[j]++则是该列的下一个非零元,如果存在的话 

	T.mu = M.nu; T.nu = M.mu; T.tu = M.tu;	//初始化矩阵T 

	T.data = (Triple*)malloc(sizeof(Triple)*(T.nu + 1));

	num = (int*)malloc((M.nu + 1)*sizeof(int));	//num和cpos开辟空间比非零元个数大1,是因为不使用0号位置 
	cpos = (int*)malloc((M.nu + 1)*sizeof(int));

	if(num == NULL || cpos == NULL)
		return OVERFLOW;

	if(T.tu != 0){
		for(j = 1; j <= M.nu; j++)	//初始化num向量 
			num[j] = 0;
		for(t = 1;t <= M.tu; t++)	//求M中每一列所含非零元的个数 
			num[M.data[t].j]++;		//这里要用到num[1]~num[5],所以上面num要全部初始化为0 

		cpos[1] = 1;	//这里是一定的 
		for(j = 2;j <= M.nu; j++)	//求每列的第一个非零元在T.data中的序号  
			cpos[j] = cpos[j-1] + num[j-1];	//画表分析得出该公式并不难 

		for(p = 1; p <= M.tu; p++){		//上面是准备工作,下面开始正式转置 
			j = M.data[p].j;	//j的作用是记录当前遍历的列,以让cops使用 
			q = cpos[j];		//是为了简化代码,因为下面都要用到cpos[j] 
			T.data[q].i = M.data[p].j;	//交换行 
			T.data[q].j = M.data[p].i;	//交换列 
			T.data[q].e = M.data[p].e;	//赋值 ,无论如何交换,储存顺序是已经定下来的了 

			cpos[j]++;	//cops[j]++则是该列的下一个非零元,如果存在的话,不存在的话也没有影响 
		}				//因为在这个for循环中,如果列变了,即j变化了,cpos[j]也不是原来的值了 
	} 
	free(num);
	free(cpos);
	return OK;
}

int main(void){
	int i,j;

	TSMatrix M;
	TSMatrix T;
	CreateSMatrix(M);
	FastTransposeSMatrix(M, T);

	printf("\n");
	return 0;
}

可以用C free等编译器进行编译运行,但由于时间关系,上面的代码中并没有给出转置后的矩阵打印的代码,可以自己加上去,当然也可以通过调试的方法监视新矩阵T中的data域的数值变化。



2.测试

测试就是按照上面的提示去做就可以了,时间关系,这里就先不做测试,改天有时间再补上吧。

时间: 2024-10-18 05:34:29

【数据结构之旅】稀疏矩阵的快速转置的相关文章

稀疏矩阵三元组快速转置(转poklau123写的很清楚)

关于稀疏矩阵的快速转置法,首先得明白其是通过对三元表进行转置.如果误以为是对矩阵进行转置,毫无疑问就算你想破脑袋也想不出个所以然,别陷入死胡同了! 对于一个三元表,行为i,列为j,值为v.需将其i与j的值对调才能得到新的三元表,但是如果直接进行转换,得到的新的三元表的顺序是混乱的,不符合三元表的规则.所以,课本首先介绍了一个用扫描来转置的算法(这个算法比较容易,在这里我就不说了),但是这个转置算法的时间复杂度太高,于是就有了接下来的快速转置算法. 要你对一个三元表进行步骤最少的转置,你可能会想,

数据结构----稀疏矩阵的快速转置

使用两种方法将稀疏矩阵快速转置 #include<iostream> #include<vector> using namespace std; template<class T> struct Triple  //三元组 { size_t row; size_t col; T _value; }; template<class T> class SparseMatrix { public: SparseMatrix(T *arr, size_t rowsi

SDUT 3347 数据结构实验之数组三:快速转置

数据结构实验之数组三:快速转置 Time Limit: 1000MS Memory Limit: 65536KB Submit Statistic Problem Description 转置运算是一种最简单的矩阵运算,对于一个m*n的矩阵M( 1 = < m < = 10000,1 = < n < = 10000 ),它的转置矩阵T是一个n*m的矩阵,且T( i , j )=M( j , i ).显然,一个稀疏矩阵的转置仍然是稀疏矩阵.你的任务是对给定一个m*n的稀疏矩阵( m

稀疏矩阵-压缩存储-列转置法- 一次定位快速转置法

稀疏矩阵的压缩存储 压缩存储值存储极少数的有效数据.使用{row,col,value}三元组存储每一个有效数据,三元组按原矩阵中的位置,以行优先级先后顺序依次存放. 压缩存储:行优先一行一行扫 有效数据存入以为矩阵_arr 列转置法 : 从前向后遍历压缩矩阵,先找列号为0的存入 转置矩阵的压缩矩阵.然后从前向后找列号为1的 ...直到转置矩阵的压缩矩阵大小和 原矩阵的一样大 这时就找完了 时间复杂度为    O(原矩阵列数 * 压缩矩阵长度) 一次定位快速转置法: 设置两个辅助矩阵 RowCou

稀疏矩阵的压缩存储及快速转置

当一个矩阵为稀疏矩阵时,有效数据的个数比无效数据要少得多,因此若将一个矩阵全部存储会浪费空间,可以只将有效数据存储起来,无效数据作为标记 代码如下: #include <iostream> #include <vector> using namespace std; //可用一个三元组来存储有效数据的信息 template<class T> struct Triple {  size_t _row;  size_t _col;  T _value; }; //系数矩阵类

稀疏矩阵的列序递增法和一次定位快速转置法

稀疏矩阵:矩阵中大多数元素为0的矩阵,从直观上讲,当非零元素个数低于总元素的30%时,这样的矩阵为稀疏矩阵. 如: int array [6][5] =     {{1, 0, 3, 0, 5}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {1, 0, 3, 0, 5}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}}; 稀疏矩阵的压缩存储:使用{row,col,value}三元组存储每一个有效数据,三元组按原矩阵中的位置,以行优先级先后顺序依次存放

稀疏矩阵的普通转置与快速转置算法

稀疏矩阵的普通转置与快速转置算法 一般来说,对于系数矩阵,我们使用三元组来存储.即就是将矩阵的所有非零元素的三元组存放在一个顺序表中,如图所示: 注意一个转置的前提:该顺序表是排好序的,即行优先,列其次. 一.普通转置 这种算法比较简单,也很容易想到: 算法思想: 对M.data从头至尾扫描: ?第一次扫描时,将M.data中列号为1的三元组赋值到T.data中 ?第二次扫描时,将M.data中列号为2的三元组赋值到T.data中 ?依此类推,直至将M.data所有三元组赋值到T.data中 代

C++实现稀疏矩阵的压缩存储、转置、快速转置

/*稀疏矩阵的压缩存储.转置.快速转置*/ #include <iostream> using namespace std; #include <vector> //三元组 template<class T> struct Triple { size_t _row; size_t _col; T _value; Triple(size_t row = 0, size_t col = 0, const T& value = T()) :_row(row) ,_co

稀疏矩阵转置+快速转置

稀疏矩阵转置 Description 稀疏矩阵的存储不宜用二维数组存储每个元素,那样的话会浪费很多的存储空间.所以可以使用一个一维数组存储其中的非零元素.这个一维数组的元素类型是一个三元组,由非零元素在该稀疏矩阵中的位置(行号和列号对)以及该元组的值构成. 矩阵转置就是将矩阵行和列上的元素对换. 现在就请你对一个稀疏矩阵进行转置.以下是稀疏矩阵转置的算法描述: 图:稀疏矩阵转置的算法描述 Input 输入的第一行是两个整数r和c(r*c <= 12500),分别表示一个包含很多0的稀疏矩阵的行数