热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

矩阵压缩存储之三元组顺序表

形态:实现:*****************************************稀疏矩阵的三元组顺序表存储表示byRowandjj201453******************

形态:


实现:

/*****************************************
稀疏矩阵的三元组顺序表存储表示
by Rowandjj
2014/5/3
******************************************/
#include
using namespace std;

#define MAXSIZE 12500//非零元个数的最大值
typedef int ElemType;
typedef struct _DATA_
{
int i;//行下标
int j;//列下标
ElemType e;//元素值
}Data,*pData;
typedef struct _MATRIX_
{
Data data[MAXSIZE+1];//非零元三元组表,data[0]不用
int mu,nu,tu;//行数,列数,非零元个数
}Matrix,*pMatrix;


bool CreateMatrix(pMatrix pMatrixTemp);//创建稀疏矩阵M
bool ClearMatrix(pMatrix pMatrixTemp);//销毁稀疏矩阵
bool AddMatrix(pMatrix pMatrixTemp3,Matrix MatrixTemp1,Matrix MatrixTemp2);//矩阵求和
bool SubMatrix(pMatrix pMatrixTemp3,Matrix MatrixTemp1,Matrix MatrixTemp2);//矩阵减运算
bool MulMatrix(pMatrix pMatrixTemp3,Matrix MatrixTemp1,Matrix MatrixTemp2);//矩阵乘运算
void Convert(pMatrix pMatrixTemp3,Matrix MatrixTemp);//矩阵转置
void FastConvert(pMatrix pMatrixTemp3,Matrix MatrixTemp);//快速转置

void printMatrix(pMatrix pMatrixTemp);

int comp(int a,int b);
//-------------------------------------------
bool CreateMatrix(pMatrix pMatrixTemp)
{
printf("请输入矩阵行数,列数,非零元个数:\n");
scanf("%d",&pMatrixTemp->mu);
scanf("%d",&pMatrixTemp->nu);
scanf("%d",&pMatrixTemp->tu);

pMatrixTemp->data[0].i = 0;
int i;
int m,n;//行,列
ElemType e;//数据
bool bOk = false;
for(i = 1; i <= pMatrixTemp->tu;i++)
{
do
{
bOk = false;
printf("请按行序顺序输入第%d个非零元素所在的行(1~%d),列(1~%d),元素值:\n",i,pMatrixTemp->mu,pMatrixTemp->nu);
scanf("%d",&m);
scanf("%d",&n);
scanf("%d",&e);
if(m<1 || m>pMatrixTemp->mu || n<1 || n>pMatrixTemp->nu)//超出范围
{
bOk = true;
}
//行或列的顺序有错,要求后一个元素的行列值大于前一个元素
if(mdata[i-1].i || m==pMatrixTemp->data[i-1].i && n<=pMatrixTemp->data[i-1].j)
{
bOk = true;
}
} while (bOk);
//给三元组赋值
pMatrixTemp->data[i].e = e;
pMatrixTemp->data[i].i = m;
pMatrixTemp->data[i].j = n;
}
return true;
}
bool ClearMatrix(pMatrix pMatrixTemp)
{
pMatrixTemp->mu = 0;
pMatrixTemp->nu = 0;
pMatrixTemp->tu = 0;
return true;
}
bool AddMatrix(pMatrix pMatrixTemp3,Matrix MatrixTemp1,Matrix MatrixTemp2)
{
//1.只有两个矩阵的行和列相等时才能相加
if(MatrixTemp1.mu != MatrixTemp2.mu)
{
return false;
}
if(MatrixTemp1.nu != MatrixTemp2.nu)
{
return false;
}
//2.初始化和矩阵的行值和列值
pMatrixTemp3->mu = MatrixTemp1.mu;
pMatrixTemp3->nu = MatrixTemp1.nu;
//3.初始化指针,为每个矩阵添加头指针和尾指针
pData pStart1 = &MatrixTemp1.data[1];
pData pEnd1 = &MatrixTemp1.data[MatrixTemp1.tu];

pData pStart2 = &MatrixTemp2.data[1];
pData pEnd2 = &MatrixTemp2.data[MatrixTemp2.tu];
//和矩阵的头尾指针默认都指向非零元素首地址的前一位(0位未存储)
pData pStart3 = pMatrixTemp3->data;
pData pEnd3 = pMatrixTemp3->data;

//4.开始合并矩阵
while(pStart1<=pEnd1 && pStart2<=pEnd2)
{
pEnd3++;
switch(comp(pStart1->i,pStart2->i))
{
case 1:
*pEnd3 = *pStart1;
pStart1++;
break;
case 0:
switch(comp(pStart1->j,pStart2->j))
{
case 1:
*pEnd3 = *pStart1;
pStart1++;
break;
case 0:
*pEnd3 = *pStart1;
pEnd3->e += pStart2->e;
if(pEnd3->e==0)//结果为0的元素不需要存储到稀疏矩阵中
{
pEnd3--;
}
pStart1++;
pStart2++;
break;
case -1:
*pEnd3 = *pStart2;
pStart2++;
break;
}
break;
case -1:
*pEnd3 = *pStart2;
pStart2++;
break;
}
}
//剩余部分直接放到和矩阵
while (pStart1<=pEnd1)
{
pEnd3++;
*pEnd3 = *pStart1;
pStart1++;
}
while (pStart2<=pEnd2)
{
pEnd3++;
*pEnd3 = *pStart2;
pStart2++;
}
//非零元个数
pMatrixTemp3->tu = pEnd3-pStart3;
return true;
}
//a[n][m] * b[m][p] = a[n][p]
bool MulMatrix(pMatrix pMatrixTemp3,Matrix MatrixTemp1,Matrix MatrixTemp2)
{
//1.矩阵1的列必须和矩阵2的行相等
if(MatrixTemp1.nu != MatrixTemp2.mu)
{
return false;
}
//2.新矩阵的行为矩阵1的行,新矩阵的列为矩阵2的列
pMatrixTemp3->mu = MatrixTemp1.mu;
pMatrixTemp3->nu = MatrixTemp2.nu;
//3.动态申请临时数组存储新矩阵的元素值
ElemType *pBase = (ElemType*)malloc(sizeof(ElemType) * (pMatrixTemp3->mu*pMatrixTemp3->nu));
if(!pBase)
{
return false;
}

int i,j;
int l = MatrixTemp2.nu;//矩阵2的列值,也就是新矩阵的列值
//给数组赋初值 memset也行
for(i = 0 ; i mu*pMatrixTemp3->nu; i++)
{
*(pBase+i) = 0;
}

//4.将矩阵相乘后的值暂时存储到申请的一维数组中
for(i = 1; i <= MatrixTemp1.tu;i++)
{
for(j = 1; j <= MatrixTemp2.tu;j++)
{
/**
*矩阵相乘的规律,矩阵1的列值等于矩阵2的行值时才相乘
**/
if(MatrixTemp1.data[i].j == MatrixTemp2.data[j].i)
{
//存储到一维数组中
*(pBase + (MatrixTemp1.data[i].i-1)*l+MatrixTemp2.data[j].j-1) += MatrixTemp1.data[i].e*MatrixTemp2.data[j].e;
}
}
}
//5.将一维数组的元素放回新矩阵中
int t = 0;
for(i = 1; i <= MatrixTemp1.mu; i++)
{
for(j = 1; j <= MatrixTemp2.nu;j++)
{
t++;
pMatrixTemp3->data[t].e = *(pBase+(i-1)*l+j-1);
pMatrixTemp3->data[t].i = i;
pMatrixTemp3->data[t].j = j;
}
}
//6.释放一维数组
free(pBase);
pMatrixTemp3->tu = t;
return true;
}
bool SubMatrix(pMatrix pMatrixTemp3,Matrix MatrixTemp1,Matrix MatrixTemp2)
{
for(int i = 1; i <= MatrixTemp2.tu;i++)
{
MatrixTemp2.data[i].e *= -1;
}
AddMatrix(pMatrixTemp3,MatrixTemp1,MatrixTemp2);
return true;
}
void Convert(pMatrix pMatrixTemp3,Matrix MatrixTemp)
{
//适用条件 tu远小于mu*nu,否则时间复杂度将会很高
pMatrixTemp3->mu = MatrixTemp.nu;
pMatrixTemp3->nu = MatrixTemp.mu;
pMatrixTemp3->tu = MatrixTemp.tu;
int q = 1;
for(int i = 1; i <= MatrixTemp.nu; i++)
{
for(int j = 1; j<= MatrixTemp.tu; j++)
{
if(i == MatrixTemp.data[j].j)
{
pMatrixTemp3->data[q].i = MatrixTemp.data[j].j;
pMatrixTemp3->data[q].j = MatrixTemp.data[j].i;
pMatrixTemp3->data[q].e = MatrixTemp.data[j].e;
q++;
}
}
}
}
//快速转置
void FastConvert(pMatrix pMatrixTemp3,Matrix MatrixTemp)
{
int i,j,k,p;

pMatrixTemp3->mu = MatrixTemp.nu;
pMatrixTemp3->nu = MatrixTemp.mu;
pMatrixTemp3->tu = MatrixTemp.tu;

//1.计算原矩阵每一列的非零元个数,存储到数组中,num[0]不存储
int *num = (int*)malloc(sizeof(int)*(MatrixTemp.nu+1));
//2.计算原矩阵每一列第一个非零元在新矩阵pMatrixTemp3->data中的位置
int *cpot = (int*)malloc(sizeof(int)*(MatrixTemp.nu+1));
if(num == NULL || cpot==NULL)
{
return;
}
if(MatrixTemp.tu > 0)//原矩阵中存在非零元
{
for(i = 1; i <= MatrixTemp.nu;i++)
{
num[i] = 0;//每一列的非零元个数初始化为0
}
for(j = 1; j <= MatrixTemp.tu; j++)
{
++num[MatrixTemp.data[j].j];//求原矩阵每一列的非零元个数
}
cpot[1] = 1;
for(k = 2;k <= MatrixTemp.nu; k++)
{
//下一列第一个非零元位置为上一列第一个非零元位置加上上一列非零元的个数
cpot[k] = cpot[k-1]+num[k-1];
}
for(p = 1; p <= MatrixTemp.tu;p++)
{
j = MatrixTemp.data[p].j;
k = cpot[j];//在新矩阵中存储的位置

pMatrixTemp3->data[k].i = MatrixTemp.data[p].j;
pMatrixTemp3->data[k].j = MatrixTemp.data[p].i;
pMatrixTemp3->data[k].e = MatrixTemp.data[p].e;
++cpot[j];//更新存储位置
}
}
free(num);
free(cpot);
}
void printMatrix(pMatrix pMatrixTemp)
{
int i;
cout<<"行数,列数,元素值"< for(i = 1; i <= pMatrixTemp->tu; i++)
{
cout<data[i].i<<","<data[i].j<<","<data[i].e< }
}
int comp(int a,int b)
{
if(a > b)
{
return 1;
}else if(a == b)
{
return 0;
}else
{
return -1;
}
}

测试:

int main()
{
Matrix matrixTemp1 = {0};
CreateMatrix(&matrixTemp1);
//Matrix matrixTemp2 = {0};
//CreateMatrix(&matrixTemp2);

Matrix matrixTemp3 = {0};
// AddMatrix(&matrixTemp3,matrixTemp1,matrixTemp2);
// MulMatrix(&matrixTemp3,matrixTemp1,matrixTemp2);
Convert(&matrixTemp3,matrixTemp1);
printMatrix(&matrixTemp3);
cout<<"------------------"< FastConvert(&matrixTemp3,matrixTemp1);
printMatrix(&matrixTemp3);

return 0;
}



推荐阅读
  • 本题要求在一组数中反复取出两个数相加,并将结果放回数组中,最终求出最小的总加法代价。这是一个经典的哈夫曼编码问题,利用贪心算法可以有效地解决。 ... [详细]
  • KMP算法是处理字符串匹配的一种高效算法它首先用O(m)的时间对模板进行预处理,然后用O(n)的时间完成匹配。从渐进的意义上说,这样时间复 ... [详细]
  • 本文探讨了符号三角形问题,该问题涉及由相同数量的“+”和“-”符号组成的三角形。通过递归回溯法,可以有效地搜索并计算符合条件的符号三角形的数量。 ... [详细]
  • 主调|大侠_重温C++ ... [详细]
  • KMP算法是一种高效的字符串模式匹配算法,能够在不进行回溯的情况下完成匹配,其时间复杂度为O(m+n),其中m和n分别为文本串和模式串的长度。本文将详细介绍KMP算法的工作原理,并提供C语言实现。 ... [详细]
  • 本文详细解析了2019年西安邀请赛中的一道树形动态规划题目——J题《And And And》。题目要求计算树中所有子路径异或值为0的集合数量,通过深入分析和算法优化,提供了高效的解决方案。 ... [详细]
  • 本文深入探讨了MySQL中常见的面试问题,包括事务隔离级别、存储引擎选择、索引结构及优化等关键知识点。通过详细解析,帮助读者在面对BAT等大厂面试时更加从容。 ... [详细]
  • 本文详细介绍了如何解压并安装MySQL集群压缩包,创建用户和组,初始化数据库,配置环境变量,并启动相关服务。此外,还提供了详细的命令行操作步骤和常见问题的解决方案。 ... [详细]
  • 本文详细介绍了C语言中的基本数据类型,包括整型、浮点型、字符型及其各自的子类型,并探讨了这些类型在不同编译环境下的表现。 ... [详细]
  • HDU 2871 内存管理问题(线段树优化)
    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2871。本题涉及内存管理操作,包括重置、申请、释放和查询内存块。通过使用线段树进行高效管理和维护。 ... [详细]
  • 本文深入探讨了UNIX/Linux系统中的进程间通信(IPC)机制,包括消息传递、同步和共享内存等。详细介绍了管道(Pipe)、有名管道(FIFO)、Posix和System V消息队列、互斥锁与条件变量、读写锁、信号量以及共享内存的使用方法和应用场景。 ... [详细]
  • 2017-2018年度《网络编程与安全》第五次实验报告
    本报告详细记录了2017-2018学年《网络编程与安全》课程第五次实验的具体内容、实验过程、遇到的问题及解决方案。 ... [详细]
  • 本题探讨如何在两个长度为 n 的整数序列中,找到它们的最长公共子序列(LCS)。题目保证第一个序列中的元素各不相同。我们将深入分析并提供一种高效的求解方法。 ... [详细]
  • 本文介绍了一个经典的算法问题——活动选择问题,来源于牛客网的比赛题目。该问题要求从一系列活动集合中选出最多数量的相容活动,确保这些活动的时间段不重叠。 ... [详细]
  • 2019年江苏大学编程考试885大题解析
    本文详细解析了2019年江苏大学编程考试中的三道大题,涵盖幂运算、扑克牌翻转和素数双胞胎的实现。通过具体代码示例,帮助考生更好地理解和掌握这些编程问题。 ... [详细]
author-avatar
苦蔷薇1988
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有