使用三元组完成二维数组转置

143 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第26天,点击查看活动详情

1、三元组

如果一个二维数组的零特别多,我们可以用一种三元组去记录这个二维数组

#define MAXIZE 100
typedef int DataType;
typedef struct
{
	int i, j;//非零元素的行、列号
	DataType v;//非零元素的值
}triple;
typedef struct
{
	triple data[MAXIZE];//非零元素的三元组表
	int m, n, t;//稀疏矩阵的行数、列数和非零元素的个数

比如这个4*5的数组,可以用右边的三元组去记录,三元组中每一个元素都记录了数组中某个元素的行列下标以及这个元素的值。 image.png 如图所示,下方的数组是上方的转置,需要注意的是三元组在记录二维数组是是由先后顺序的,图示的是按顺序一行一行记录的。

2、跳着找,顺着存

//跳着找,顺着存 t<<m*n
tripletable transmatrix(tripletable a)
{
	tripletable b;//转置后的三元组
	int p, q, col;
	b.m = a.n;//行属与列数相反
	b.n = a.m;
	b.t = a.t;//非零元素个数相同。
	if (b.t)//新三元组的元素个数,及非零元素的个数s
	{
		q = 0;
		for (col = 1; col <= a.n; col++) {//a.n=A数组的列数
			for (p = 0; p < a.t; p++) {//遍历所有的非零元素
				if (a.data[p].j == col)//如果
				{
					b.data[q].i = col;
					b.data[q].j = a.data[p].i;
					b.data[q].v = a.data[p].v;
					q++;//顺着存
				}
			}
		}
	}
	return b;
}

3、顺着找,跳着存

//顺着找,跳着存 
tripletable transmatrix2(tripletable a) 
{
	tripletable b;
	int p, q, col, k;
	int num[10] , pot[10];//如果编译器循序的话就可用num[a.t] pot[a.n];
	b.m = a.n; b.n = a.m; b.t = a.t;
	if (b.t)
	{
		for (col = 1; col <= a.n; ++col)
		{
			num[col] = 0;
		}
		for (k = 0; k < a.t; ++k)
		{
			++num[a.data[k].j];
		}
		pot[1] = 0;
		for (col = 2; col <= a.n; ++col)
			pot[col] = pot[col - 1] + num[col - 1];
		for (p = 0; p < a.t; ++p) {
			col = a.data[p].j;
			q = pot[col];
			b.data[q].i = a.data[p].j;
			b.data[q].j = a.data[p].i;
			b.data[q].v = a.data[p].v;
			++pot[col];
		}
	}
	return b;
}

4,排序找法

image.png 如图所示,要完成转置可以分为两个步骤: (1):i列与j列的内容互换 (2):以i为准进行排序


//排序法
tripletable transmatrix3(tripletable a)
{
	tripletable b;//转置后的三元组
	int p, q, col;
	b.m = a.n;//行属与列数相反
	b.n = a.m;
	b.t = a.t;//非零元素个数相同。
	if (b.t)
	{
                //i列 与j列互换
		for (int s = 0; s < b.t; s++) {
			b.data[s].i = a.data[s].j;
			b.data[s].j = a.data[s].i;
			b.data[s].v = a.data[s].v;
		}//O(n)
                // 冒泡排序
		for (int k = 0; k < b.t-1; k++) {
			for (int h = 0; k < b.t-k-1; h++) {
				if (b.data[h].i > b.data[h + 1].i)
				{
					triple temp = b.data[h];
					b.data[h + 1] = b.data[h];
					b.data[h] = temp;
				}
			}//O(n~2)不到
		}
	}
	return b;
}

5、测试

void Print(tripletable a)//打印三元组
{
	tripletable b = a;
	for (int i = 0; i < b.t; i++) {
		printf("%d %d %d\n", b.data[i].i, b.data[i].j, b.data[i].v);
	}
}
void Cin(tripletable *a)//输入三原组
{
	tripletable *b = a;
	for (int i = 0; i < b->t; i++) {
		scanf("%d%d%d", &b->data[i].i, &b->data[i].j, &b->data[i].v);
	}
}
void test01()
{
	printf("转置前:\n");
	tripletable a,b;
	a.m = 4; a.n = 5; a.t = 5;
	Cin(&a);
	b = transmatrix(a);
	printf("转置后:\n");
	Print(b);
}

image.png