严书----数据结构----P98
这次的实验是完成稀疏矩阵的转置:
原理:首先稀疏矩阵的非零值远小于总个数的,所以可以用一个三元组将该矩阵存储起来,但是这样的话在进行转置的时候就没那么直观了,就不只是交换行列那样,所以就要用到今天的方法.如下:
下面用两种方法实现,一种是直接按照列的值进行重排,另一种是快速转置
储存压缩矩阵有两种方式,一种是用二维数组来储存三元组,另一种是直接写在结构体里
(注意:用二维数组储存三元组的方法很好用,使用于出现三个变量,eg:x,y,val这种形式,在ACM也经常用到)
方法一:
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
using namespace std;
/*
三元组传入一个稀疏矩阵,即不为零的个数<=0.05
把矩阵转化为转置矩阵,
注意:矩阵得设置一个具体矩阵出来
eg:10*10并将其打印出来.
步骤:
1.将矩阵的行列值相互交换,将每个三元组的i和j相互调换
2.重排三元组之间的次序便可实现矩阵的转置
*/
//终于成功....睡觉...一次是在for循环后面加了;,一次是for循环<=写成了<....循环还是要认真写啊,,,,
const int maxn = 10;
//对三元组的val值进行排序
//用第一种排序方法:按照原矩阵的列序来进行转置
void sort_triple(int (*pTriple)[3], int (*pnewTriple)[3])
{
pnewTriple[0][0] = pTriple[0][1];
pnewTriple[0][1] = pTriple[0][0];
pnewTriple[0][2] = pTriple[0][2];
if (pnewTriple[0][2])
{
int cnt = 1;
for (int col = 1; col <= pTriple[0][1]; col++)//按原来的列来,对原来的每一列
{
for (int t = 1; t <= pTriple[0][2]; t++) //遍历所有非零数
{
if (pTriple[t][1] == col)//如果存入的值是属于这一列的
{
pnewTriple[cnt][0] = pTriple[t][1];
pnewTriple[cnt][1] = pTriple[t][0];
pnewTriple[cnt][2] = pTriple[t][2];
cnt++;
}
}
}
//printf("cnt %d %d \n",cnt, pnewTriple[3][2]);
}
}
int main()
{
int matrix[10][10] = {
{ 0,0,0,0,0,0,4,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,8,0 },
{ 0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0 },
{ 0,0,2,0,0,0,0,0,0,0 },
{ 0,0,0,1,0,0,0,0,0,0 }
};
int triple[maxn + 1][3] = { maxn,maxn,0 }; //用于存储稀疏矩阵信息的三元组(矩阵压缩)
//将已知的矩阵用三元组表示
int cnt = 0;//矩阵的元素个数
for (int i = 0; i < maxn; i++)
{
for (int j = 0; j < maxn; j++)
{
if (matrix[i][j])
{
triple[++cnt][0] = i;
triple[cnt][1] = j;
triple[cnt][2] = matrix[i][j];
}
}
}
// printf("%d cnt \n", cnt);
triple[0][2] = cnt;
int newTriple[maxn+1][3];
//对三元组的值进行排序
sort_triple(triple,newTriple);
//输出矩阵
int new_matrix[maxn][maxn] = { 0 };
// printf("%d ... cnt", newTriple[0][2]);
for (int i = 1; i <= newTriple[0][2]; i++)
{
int x = newTriple[i][0];
int y = newTriple[i][1];
int value = newTriple[i][2];
new_matrix[x][y] = value;
}
puts("转置前:");
for (int i = 0; i < maxn; i++)
{
for (int j = 0; j < maxn; j++)
{
printf("%d ", matrix[i][j]);
}
puts("");
}
puts("转置后:");
for (int i = 0; i < maxn; i++)
{
for (int j = 0; j < maxn; j++)
{
printf("%d ", new_matrix[i][j]);
}
puts("");
}
system("pause");
return 0;
}
方法二:
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
using namespace std;
//快速转置法
/*
三元组传入一个稀疏矩阵,即不为零的个数<=0.05
把矩阵转化为转置矩阵,
注意:矩阵得设置一个具体矩阵出来
eg:10*10并将其打印出来.
步骤:
1.将矩阵的行列值相互交换,将每个三元组的i和j相互调换
2.重排三元组之间的次序便可实现矩阵的转置
*/
//可以试一下这种用cmp进行排序的
/*
bool cmp(int(*a)[3], int(*b)[3])
{
if (*a + 0 < *b + 0) return true;
else if (*a + 0 == *b + 0)
return *a + 1 < *b + 1;
else return false;
}*/
const int maxn = 10;
typedef struct {
int i, j;
int val;
}Triple;
typedef struct {
Triple data[maxn + 1];
int row, col, sum;//行数,列数,非零元个数
}TSMatrix;
//对矩阵的val值进行排序
//用第二种排序方法:按照原矩阵的列序来进行转置
/*
M是原来的矩阵,T是新的矩阵
num[col]是M中第col列非零元的个数
cpot[col]是M中第col列第一个非零元在第二个b.data的位置
*/
void sort_triple(TSMatrix M, TSMatrix &T)//
{
T.row = M.col;
T.col = M.row;
T.sum = M.sum;
int num[maxn+1];//num[col]是M中第col列非零元的个数
int cpot[maxn+1];//cpot[col]是M中第col列第一个非零元在b.data的位置
if (T.sum)
{
for (int col = 1; col <= M.col; col++) num[col] = 0;
for (int i = 1; i <= M.sum; i++) num[M.data[i].j]++;//求M每一列的非零元个数
cpot[1] = 1;
for (int i = 2; i <= M.col; i++) cpot[i] = cpot[i - 1] + num[i - 1];
for (int i = 1; i <= M.sum; i++)
{
int col = M.data[i].j;
int tt = cpot[col];
T.data[tt].i = M.data[i].j;
T.data[tt].j = M.data[i].i;
T.data[tt].val = M.data[i].val;
cpot[col]++;//用掉一个,这一列非零元开始的位置就要增加一
}//for
}//if
}
int main()
{
int matrix[10][10] = {
{ 0,0,0,0,0,0,4,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,8,0 },
{ 0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0 },
{ 0,0,2,0,0,0,0,0,0,0 },
{ 0,0,0,1,0,0,0,0,0,0 }
};
TSMatrix aa;
int cnt = 0;//矩阵的元素个数
for (int i = 0; i < maxn; i++)
{
for (int j = 0; j < maxn; j++)
{
if (matrix[i][j])
{
aa.data[++cnt].i = i;
aa.data[cnt].j = j;
aa.data[cnt].val = matrix[i][j];
}
}
}
aa.row = maxn;
aa.col = maxn;
aa.sum = cnt;
TSMatrix new_aa;
//对三元组的值进行排序
sort_triple(aa, new_aa);
//输出矩阵
int new_matrix[maxn][maxn] = { 0 };
for (int i = 1; i <= new_aa.sum; i++)
{
int x = new_aa.data[i].i;
int y = new_aa.data[i].j;
int value = new_aa.data[i].val;
new_matrix[x][y] = value;
}
puts("转置前:");
for (int i = 0; i < maxn; i++)
{
for (int j = 0; j < maxn; j++)
{
printf("%d ", matrix[i][j]);
}
puts("");
}
puts("转置后:");
for (int i = 0; i < maxn; i++)
{
for (int j = 0; j < maxn; j++)
{
printf("%d ", new_matrix[i][j]);
}
puts("");
}
system("pause");
return 0;
}
也可以试试下面这样用sort来排里面的val值.具体还没写完整,应该差不多这样
bool cmp(int(*a)[3], int(*b)[3])
{
if (*a + 0 < *b + 0) return true;
else if (*a + 0 == *b + 0)
return *a + 1 < *b + 1;
else return false;
}