实验名称:矩阵快速转置算法实现
实验一
- 实验目的
二、实验环境
1、visual studio2019
三、实验内容
1. 实现矩阵快速转置
源程序:
// ConsoleApplication2.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//矩阵的快速转置算法实现;
#include <iostream>
using namespace std;
#define MAXSIZE 12500
#define OK 1
typedef int Status;
typedef struct {
int i, j;
int e;
}Triple;//三元组
typedef struct {
Triple data[MAXSIZE+1];//这个Data是什么,竖着的一整行
int mu, nu, tu;//矩阵行数列数和非零元个数
} TMatrix;//三元组矩阵吗
/*做到转置1.将矩阵行和列的值交换,2.将元祖中i和j的值交换3,重新排列三元组之间的次序*/
/*Status TransposeMartix(TMatrix M, TMatrix& T)
{
T.mu = M.mu;
T.nu = M.nu;
T.tu = M.tu;
if (T.tu) {
int q = 1;
for (int col = 1; col <= M.nu; col++)//why ++col,第一个元素不需要变换?
{
for (int p = 1; p <= M.mu; p++)//应该是mu?
{
if (M.data[p].j == col)
{
T.data[q].i = M.data[p].j;
T.data[q].j = M.data[p].i;
T.data[q].e = M.data[p].e;
++q;
}
}
}
}
return OK;
}*/
//首先需要先计算同一列的个数有多少,放到num(col)里,然后再放当前位置在表中,并更新
//要创建一个表
//疑问点;哪个是矩阵哪个是三元组,想计算同一列有多少个怎么计算
//循环顺序扫描,col=M.data[p].j col++遇到了同一个就+1;但是顺序怎么办,哦哦主列已有顺序 放一个cpot[col]
// 下一个cpot[col]=cpot[col-1]+num[cpot-1]上一个第一个位置加上非零元的数量就等于下一个非零元的位置【指在三元组表里】
//如何放进去cpot[col]
//② 三元表T可能没有初始化,这句的意思是将矩阵M的行数,列数,以及非零元个数传给矩阵T,使其初始化。
//③ T.tu为真时,即矩阵M中至少存在一个非零元。
TMatrix TransposeMartix(TMatrix M, TMatrix& T)
{
T.mu = M.nu;
T.nu = M.mu;
T.tu = M.tu;//initialize
int num[50];
int cpot[50];
if (T.nu) {
for (int col = 1; col <= T.mu; ++col)//遍历每一行
{ //初始化这个
num[col] = 0;
};
for (int t = 1; t <= T.mu; ++t) {
++num[M.data[t].j];//smart step!
}
cpot[1] = 1;
for (int col = 2; col <= M.nu; ++col) {
cpot[col] = cpot[col - 1] + num[col - 1];
}
for (int p = 1; p <= T.mu; ++p) {
int col = M.data[p].j;
T.data[cpot[col]].i = col;
T.data[cpot[col]].j = M.data[p].i;
T.data[cpot[col]].e = M.data[p].e;
++cpot[col];
}
}
cout << "转置成功" << endl;
return T;
}
int main()
{
TMatrix M;
TMatrix T;
M.mu = 2;
M.nu= 3;
M.tu = 4;
M.data[0].i = 1;
M.data[0].j = 2;
M.data[0].e = 1;
M.data[1].i = 2;
M.data[1].j = 2;
M.data[1].e = 3;
M.data[2].i = 3;
M.data[2].j = 1;
M.data[2].e = 6;
M.data[3].i = 3;
M.data[3].j = 2;
M.data[3].e = 5;
T = TransposeMartix(M, T);
printf("使用快速转置:\n");
for (int i = 1; i <= M.nu; i++) {
printf("(%d,%d,%d)\n", T.data[i].i, T.data[i].j, T.data[i].e);
}
}
运行结果截图:
运行结果分析:
快速转置是为了解决用传统方法1.冒泡排序遍历时间复杂度高o(n2
三元组ij互换后再根据i列数大小重新排序
- o(n*t
{1}先用for (int t = 1; t <= T.mu; ++t) {
++num[M.data[t].j];//smart step!
}
获得每一个相同j值的个数,用num[]储存。如num[2]=3,即原三元组矩阵中j为2的行数为3。转置后代表需要留三行空位给i=2的元组。
{2}用cpot[1] = 1;
for (int col = 2; col <= M.nu; ++col) {
cpot[col] = cpot[col - 1] + num[col - 1];
}
这个来获得每个转置后的i所需要的行位置,比如原来i=2时位置是在第二排,即cpot[2]=cpot[1]+num[1]=2;那么如果num[2]=3,即i=2的有三行,那么下一个i值就应该从cpot[2]+num[2]=5开始,即cpot[3]=5。
{3}for (int p = 1; p <= T.mu; ++p) {
int col = M.data[p].j;
T.data[cpot[col]].i = col;
T.data[cpot[col]].j = M.data[p].i;
T.data[cpot[col]].e = M.data[p].e;
++cpot[col];
}
用这个来把相应的原来矩阵M的data[].i j e按照cpot里标记的位置赋给新的转置矩阵T。因为原来矩阵M同i值元组的j也按顺序排列,所以不需要考虑顺序赋值会乱的问题。
{4}最后测试输出矩阵
for (int i = 1; i <= M.nu; i++) {
printf("(%d,%d,%d)\n", T.data[i].i, T.data[i].j, T.data[i].e);
}
}
通过实验练习了快速排序算法,同时加深了对时间复杂度的理解。