三元组是计算机专业的一门公共基础课程——数据结构里的概念。主要是用来存储稀疏矩阵的一种压缩方式,也叫三元组表。假设以顺序存数结构来表示三元组表(triple table),则得到稀疏矩阵的一种压缩存储方式,即三元组顺序表,简称三元组表。
——百度百科
在本文我将介绍两种三元组的转置方式,一是普通的遍历转置,第二种是所谓的快速转置
目录
声明
#include<iostream>
#include<fstream>
using namespace std;
typedef int ElemType; // 假设元素类型为整型
#define MAXSIZE 256 // 设定非零元素个数初始最大值
typedef struct Triple {
int i, j;
ElemType data;
};
class SqSMatrix
{
private:
Triple arr[MAXSIZE]; // 非零元素三元组
int Rows, Cols, Nums; // 矩阵的行数、列数、非零元素个数
public:
SqSMatrix(SqSMatrix& b);//拷贝构造函数
SqSMatrix();//构造函数
void TransposeSMatrix(SqSMatrix& b);//普通转置
void FastTransposeSMatrix(SqSMatrix& b);//快速转置
void travel();//三元组遍历输出
};
普通转置
普通转置的思想是极为朴素的,我们做Cols趟循环,每次将列数等于我们扫描遍数的三元组i,j交换存到新的矩阵中,这样得到的矩阵就是转置后的矩阵,整理思路如下
1.进行Cols次大循环
2.第k次循环中,对原三元组进行整体扫描,寻找列数为k的三元组,完成对k列的转置存储
void SqSMatrix::TransposeSMatrix(SqSMatrix& b)
{
b.Rows = Cols; // 矩阵 b 的行数等于矩阵 A 的列数
b.Cols = Rows; // 矩阵 b 的列数等于矩阵 A 的行数
b.Nums = Nums; // 矩阵 b 的非零元素数等于矩阵 A 的非零元素数
if (Nums > 0)
{ // 若非零元素个数不为零
int q = 0; // b.arr 的当前位置
for (int k = 0; k <= Cols; k++)
{
for (int p = 0; p < Nums; p++) // 每趟对 A 所有三元组进行扫描
{
if (arr[p].j == k)
{ // 若第 p 个三元组中元素的列号为 k
b.arr[q].i = arr[p].j; // 新三元组中的行号
b.arr[q].j = arr[p].i; // 新三元组中的列号
b.arr[q].data = arr[p].data; // 新三元组中的值
q++; // b.arr 的当前位置增加 1
}
}
}
}
}
快速转置
快速转置仅做了一次扫描,将转置后矩阵每行的非零元素进行了统计,根据这个数组我们算前缀和就可以得到转置后每一行元素开始存储的第一个位置,然后我们再对原矩阵的三元组进行遍历,根据其列数存到相应的位置,然后再将这一行开始存储元素的位置向后跳一位,两次遍历完成了转置,整理一下思路如下:
1.扫描,统计转制后每行的元素个数记载num0数组中
2.计算num0数组的前缀和,前n项和存到start[n-1]中,前一项和不存
3.遍历原三元组,根据start和其列数确定其在新三元组内的位置,加入后,将相应的start中的数加一,跳到下一位
void SqSMatrix::FastTransposeSMatrix(SqSMatrix& b)
{
b.Cols = Rows;
b.Rows = Cols;
b.Nums = Nums;
int* num0 = new int[Cols];//用以记录转制后每行的元素个数
int* start = new int[Cols];//用以记录转制后每行第一个元素的位置
start[0] = 0;
for (int i = 0; i <= Cols; i++)
{
num0[i] = 0;
}
for (int i = 0; i < Nums; i++)
{
num0[arr[i].j]++;
}
for (int i = 1; i <= Cols; i++)
start[i] = start[i - 1] + num0[i - 1];
for (int k = 0; k < Nums; k++)
{
int p = start[arr[k].j];
b.arr[p].i = arr[k].j;
b.arr[p].j = arr[k].i;
b.arr[p].data = arr[k].data;
start[arr[k].j]++;
}
}
源代码
#include<iostream>
#include<fstream>
using namespace std;
typedef int ElemType; // 假设元素类型为整型
#define MAXSIZE 256 // 设定非零元素个数初始最大值
typedef struct Triple {
int i, j;
ElemType data;
};
class SqSMatrix
{
private:
Triple arr[MAXSIZE]; // 非零元素三元组
int Rows, Cols, Nums; // 矩阵的行数、列数、非零元素个数
public:
SqSMatrix(SqSMatrix& b);
SqSMatrix();
void TransposeSMatrix(SqSMatrix& b);
void FastTransposeSMatrix(SqSMatrix& b);
void travel();
};
int main()
{
SqSMatrix a;
a.travel();
cout << endl;
SqSMatrix b(a);
b.travel();
cout << endl;
a.TransposeSMatrix(b);
b.travel();
cout << endl;
a.FastTransposeSMatrix(b);
b.travel();
cout << endl;
}
SqSMatrix::SqSMatrix(SqSMatrix& b)
{
Rows = b.Rows;
Cols = b.Cols;
Nums = b.Nums;
for (int i = 0; i < Nums; i++)
{
arr[i].data = b.arr[i].data;
arr[i].i = b.arr[i].i;
arr[i].j = b.arr[i].j;
}
}
SqSMatrix::SqSMatrix()
{
fstream file("text.txt", ios::in);
file >> Rows>> Cols >> Nums;
for (int i = 0; i < Nums; i++)
{
file >> arr[i].i >> arr[i].j >> arr[i].data;
}
}
void SqSMatrix::TransposeSMatrix(SqSMatrix& b)
{
b.Rows = Cols; // 矩阵 b 的行数等于矩阵 A 的列数
b.Cols = Rows; // 矩阵 b 的列数等于矩阵 A 的行数
b.Nums = Nums; // 矩阵 b 的非零元素数等于矩阵 A 的非零元素数
if (Nums > 0)
{ // 若非零元素个数不为零
int q = 0; // b.arr 的当前位置
for (int k = 0; k <= Cols; k++)
{
for (int p = 0; p < Nums; p++) // 每趟对 A 所有三元组进行扫描
{
if (arr[p].j == k)
{ // 若第 p 个三元组中元素的列号为 k
b.arr[q].i = arr[p].j; // 新三元组中的行号
b.arr[q].j = arr[p].i; // 新三元组中的列号
b.arr[q].data = arr[p].data; // 新三元组中的值
q++; // b.arr 的当前位置增加 1
}
}
}
}
}
void SqSMatrix::FastTransposeSMatrix(SqSMatrix& b)
{
b.Cols = Rows;
b.Rows = Cols;
b.Nums = Nums;
int* num0 = new int[Cols];//用以记录转制后每行的元素个数
int* start = new int[Cols];//用以记录转制后每行第一个元素的位置
start[0] = 0;
for (int i = 0; i <= Cols; i++)
{
num0[i] = 0;
}
for (int i = 0; i < Nums; i++)
{
num0[arr[i].j]++;
}
for (int i = 1; i <= Cols; i++)
start[i] = start[i - 1] + num0[i - 1];
for (int k = 0; k < Nums; k++)
{
int p = start[arr[k].j];
b.arr[p].i = arr[k].j;
b.arr[p].j = arr[k].i;
b.arr[p].data = arr[k].data;
start[arr[k].j]++;
}
}
void SqSMatrix::travel()
{
for (int k = 0; k < Nums; k++)
{
cout << arr[k].i << ' ' << arr[k].j << ' ' << arr[k].data << endl;
}
}