热门标签 | 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算法中next数组的构建及其应用,重点分析了未改良和改良后的next数组在字符串匹配中的作用。通过具体实例和代码实现,帮助读者更好地理解KMP算法的核心原理。 ... [详细]
  • C++实现经典排序算法
    本文详细介绍了七种经典的排序算法及其性能分析。每种算法的平均、最坏和最好情况的时间复杂度、辅助空间需求以及稳定性都被列出,帮助读者全面了解这些排序方法的特点。 ... [详细]
  • 题目描述:给定n个半开区间[a, b),要求使用两个互不重叠的记录器,求最多可以记录多少个区间。解决方案采用贪心算法,通过排序和遍历实现最优解。 ... [详细]
  • 在金融和会计领域,准确无误地填写票据和结算凭证至关重要。这些文件不仅是支付结算和现金收付的重要依据,还直接关系到交易的安全性和准确性。本文介绍了一种使用C语言实现小写金额转换为大写金额的方法,确保数据的标准化和规范化。 ... [详细]
  • UNP 第9章:主机名与地址转换
    本章探讨了用于在主机名和数值地址之间进行转换的函数,如gethostbyname和gethostbyaddr。此外,还介绍了getservbyname和getservbyport函数,用于在服务器名和端口号之间进行转换。 ... [详细]
  • 扫描线三巨头 hdu1928hdu 1255  hdu 1542 [POJ 1151]
    学习链接:http:blog.csdn.netlwt36articledetails48908031学习扫描线主要学习的是一种扫描的思想,后期可以求解很 ... [详细]
  • 题目Link题目学习link1题目学习link2题目学习link3%%%受益匪浅!-----&# ... [详细]
  • 本文探讨了 C++ 中普通数组和标准库类型 vector 的初始化方法。普通数组具有固定长度,而 vector 是一种可扩展的容器,允许动态调整大小。文章详细介绍了不同初始化方式及其应用场景,并提供了代码示例以加深理解。 ... [详细]
  • 本题探讨了一种字符串变换方法,旨在判断两个给定的字符串是否可以通过特定的字母替换和位置交换操作相互转换。核心在于找到这些变换中的不变量,从而确定转换的可能性。 ... [详细]
  • 本文介绍如何使用Objective-C结合dispatch库进行并发编程,以提高素数计数任务的效率。通过对比纯C代码与引入并发机制后的代码,展示dispatch库的强大功能。 ... [详细]
  • 本实验主要探讨了二叉排序树(BST)的基本操作,包括创建、查找和删除节点。通过具体实例和代码实现,详细介绍了如何使用递归和非递归方法进行关键字查找,并展示了删除特定节点后的树结构变化。 ... [详细]
  • 火星商店问题:线段树分治与持久化Trie树的应用
    本题涉及编号为1至n的火星商店,每个商店有一个永久商品价值v。操作包括每天在指定商店增加一个新商品,以及查询某段时间内某些商店中所有商品(含永久商品)与给定密码值的最大异或结果。通过线段树分治和持久化Trie树来高效解决此问题。 ... [详细]
  • 本文基于刘洪波老师的《英文词根词缀精讲》,深入探讨了多个重要词根词缀的起源及其相关词汇,帮助读者更好地理解和记忆英语单词。 ... [详细]
  • 在前两篇文章中,我们探讨了 ControllerDescriptor 和 ActionDescriptor 这两个描述对象,分别对应控制器和操作方法。本文将基于 MVC3 源码进一步分析 ParameterDescriptor,即用于描述 Action 方法参数的对象,并详细介绍其工作原理。 ... [详细]
  • C++: 实现基于类的四面体体积计算
    本文介绍如何使用C++编程语言,通过定义类和方法来计算由四个三维坐标点构成的四面体体积。文中详细解释了四面体体积的数学公式,并提供了两种不同的实现方式。 ... [详细]
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社区 版权所有