特殊矩阵的压缩存储

压缩存储的定义:
若多个数据元素的值都相同,则只分配一个元素值的存储空间,且
零元素不占存储空间。
能够压缩的一些矩阵: 一些特殊矩阵,如:对称矩阵,对角矩阵,三角矩阵,稀疏矩阵等。 稀疏矩阵定义:
矩阵中非零元素的个数较少(一 般小于5%)

一、对称矩阵

特点:

在n×n的矩阵a中,aij=aji(1<=i,j<=n)

存储方法:

只存储下(或者上)三角(包括主对角线)的数据元素。共占用n(n+1)/2个元素空间 可以以行序为主序将元素存放在一个一维数组**sa[n(n+1)/2]**中。

二、三角矩阵

特点:

对角线以下(或者以上)的数据元素(不包括对角线)全部为常数c

存储方法:

重复元素c共享一个元素存储空间,共占用m(n+1)/2+1个元素 空间:sa[1…n(n+1)/2+1]

三、对角矩阵(带状矩阵)

特点:

在n×n的方阵中,所有非零元素都集中在以主对角线为中心的带状区域中,区域外的值全为0,则成为对角矩阵。常见的有三对角矩阵,五对角矩阵,七对角矩阵等。

例:三对角矩阵

a[k]=2+3(i-2)+(j-i-2)-1=2*i+j-3

存储方法

四、稀疏矩阵的存储

**稀疏矩阵:**设在m×n的矩阵中有t个非零元素。令x=t/(m×n),当x<=0.05时称为稀疏矩阵

**三元组(i,j,aij)**唯一确定矩阵的一个非零元

**压缩存储原则:**存各非零元的值,行列位置和矩阵的行列数

稀疏矩阵的压缩存储方法——顺序存储结构

三元组顺序表

三元组顺序表又称有序的双下标法

三元组顺序表的优点:非零元在表中按行序有序存储,因此便于进行依行顺序处理的矩阵运算

三元组顺序表的缺点:**不能随机存取。**若按行号存取某一行中的非零元,则需重头开始进行查找。

顺序存储结构

typedef int ElemType;
//----------稀疏矩阵的三元组顺序表存储表示----------
#define MAXSIZE 12500   //假设非零元个数的最大值为12500
typedef struct {int i, j;   //该非零元的行下标和列下标ElemType e;
} Triple;typedef struct {Triple data[MAXSIZE + 1];     //非零元三元组表,data[0]未用int mu, nu, tu;   //矩阵的行数,列数,和非零元的个数
} TSMatrix;

打印矩阵

void PrintfTSMatrix(TSMatrix X){//打印矩阵int m,n;m=X.mu;   //稀疏矩阵的行数n=X.nu;   //稀疏矩阵的列数int k=1;  //三元组数组的下标for(int i=0;i<m;i++){for(int j=0;j<n;j++){    //双层循环遍历稀疏矩阵if(i==X.data[k].i&&j==X.data[k].j){ //如果i和j能够匹配三元组的下标printf("%d\t",X.data[k].e);  //如果能够配对则输出三元组的非零元素的值k++; //继续遍历三元组的元素}else{printf("0\t");  //如果没有匹配则代表该处位置是0}}printf("\n");}
}

求稀疏矩阵的转置矩阵

int TransposeSMatrix(TSMatrix M, TSMatrix &T) {//采用三元组表存储表示,求稀疏矩阵M的转置矩阵TT.mu = M.nu;T.nu = M.mu;T.tu = M.tu;int q,p;if (T.tu) {q = 1;for (int col = 1; col <= M.nu; ++col) {   //按M的列查找for (p = 1; p <= M.tu; ++p) {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 0;
}

求稀疏矩阵的转置矩阵(快速转置)

链接: 看这个好理解

//快速转置
int FastTransposeSMatrix(TSMatrix M, TSMatrix &T) {//采用三元组顺序表存储表示,求稀疏矩阵M的转置矩阵TT.mu = M.nu;T.nu = M.mu;T.tu = M.tu;int col, num[1000], cpot[1000];int p, q;if (T.tu) {for (col = 1; col <= M.nu; ++col) num[col] = 0;for (int t = 1; t <= M.tu; ++t)    ++num[M.data[t].j];   //求M中每一列含非零元个数cpot[1] = 1; //Cpot[1]=1的用处是第一列的在新三元表T的第一个插入位置为1。Cpot[0]是留给储存三元表行列数和非零元个数的。for (col = 2; col <= M.tu; ++col) cpot[col] = cpot[col - 1] + num[col - 1]; //求第col列中第一个非零元在b.data中的序号for (p = 1; p <= M.tu; ++p) {col = M.data[p].j;q = cpot[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;++cpot[col];}}return 0;
}

稀疏矩阵的链式存储结构:十字链表

优点:它能够灵活地插入因运算而产生的新的非零元素,删除因运算而产生的新的零元素,实现矩阵的各种运算。

在十字链表中,矩阵的每一个非零元素用一个结点表示,该结点除了(row,col,value)以外,还要有两个域: **right:**用于链接同一行中的下一个非零元素; **down:**用于链接同一列中的下一个非零元素;

十字链表中结点的结构示意图 :

十字链表的建立

CrossList CreatSMatrix_OL(CrossList &M) {//创建稀疏矩阵M.采用十字链表存储表示int m, n, t;int i, j, e;OLink p, q;scanf("%d%d%d", &m, &n, &t);   //输入M的行数,列数和非零元个数M.mu = m;M.nu = n;M.tu = t;if (!(M.rhead = (OLink *)malloc((m + 1) * sizeof(OLink))))  exit(0);if (!(M.chead = (OLink *)malloc((n + 1) * sizeof(OLink))))    exit(0);for (i = 1; i <= m; i++) M.rhead[i] = NULL;for (j = 1; j <= n; j++)   M.chead[j] = NULL;    //初始化行列头指针向量;各行列链表为空链表for (scanf("%d%d%d", &i, &j, &e);i!=0;scanf("%d%d%d",&i,&j,&e)) {if(!(p=(OLNode*)malloc(sizeof(OLNode)))){printf("初始化三元组失败"); exit(0);}p->i=i; p->j=j; p->e=e; //生成结点if(NULL==M.rhead[i]||M.rhead[i]->j>j){    p->right=M.rhead[i];M.rhead[i]=p;}else{    //寻查在行表中的插入位置for(q=M.rhead[i];(q->down)&&q->right->j<j;q=q->right);p->right=q->right;   q->right=p; //完成行插入 }if(NULL == M.chead[j] || M.chead[j]->i > i){p->down=M.chead[j];M.chead[j]=p;}else{    //寻查在列表中的插入位置for(q=M.chead[i];(q->down)&&q->down->i<i;q=q->down);p->down=q->down;q->down=p;}    }return M;
}

十字链表的完整代码

测试样例:

输入矩阵的行数、列数和非0元素个数:3 3 3
2 2 3
2 3 4
3 2 5
0 0 0
输出矩阵M:
2 2 3
3 2 5
2 3 4

#include<stdio.h>
#include<stdlib.h>
typedef struct OLNode {int i, j, e; //矩阵三元组i代表行 j代表列 e代表当前位置的数据struct OLNode *right, *down; //指针域 右指针 下指针
} OLNode, *OLink;
typedef struct {OLink *rhead, *chead; //行和列链表头指针int mu, nu, tu;  //矩阵的行数,列数和非零元的个数
} CrossList;
CrossList CreateMatrix_OL(CrossList M);
void display(CrossList M);
int main() {CrossList M;M.rhead = NULL;M.chead = NULL;M = CreateMatrix_OL(M);printf("输出矩阵M:\n");display(M);return 0;
}
CrossList CreateMatrix_OL(CrossList M) {int m, n, t;int i, j, e;OLNode *p, *q;printf("输入矩阵的行数、列数和非0元素个数:");scanf("%d%d%d", &m, &n, &t);M.mu = m;M.nu = n;M.tu = t;if (!(M.rhead = (OLink*)malloc((m + 1) * sizeof(OLink))) || !(M.chead = (OLink*)malloc((n + 1) * sizeof(OLink)))) {printf("初始化矩阵失败");exit(0);}for (i = 1; i <= m; i++) {M.rhead[i] = NULL;}for (j = 1; j <= n; j++) {M.chead[j] = NULL;}for (scanf("%d%d%d", &i, &j, &e); 0 != i; scanf("%d%d%d", &i, &j, &e)) {if (!(p = (OLNode*)malloc(sizeof(OLNode)))) {printf("初始化三元组失败");exit(0);}p->i = i;p->j = j;p->e = e;//链接到行的指定位置if (NULL == M.rhead[i] || M.rhead[i]->j > j) {p->right = M.rhead[i];M.rhead[i] = p;} else {for (q = M.rhead[i]; (q->right) && q->right->j < j; q = q->right);p->right = q->right;q->right = p;}//链接到列的指定位置if (NULL == M.chead[j] || M.chead[j]->i > i) {p->down = M.chead[j];M.chead[j] = p;} else {for (q = M.chead[j]; (q->down) && q->down->i < i; q = q->down);p->down = q->down;q->down = p;}}return M;
}
void display(CrossList M) {for (int i = 1; i <= M.nu; i++) {if (NULL != M.chead[i]) {OLink p = M.chead[i];while (NULL != p) {printf("%d\t%d\t%d\n", p->i, p->j, p->e);p = p->down;}}}
}

特殊矩阵的压缩存储(对称矩阵,三角矩阵,对角矩阵,稀疏矩阵的顺序,链序存储,十字链表的建立)相关推荐

  1. 一维数组二维数组对称矩阵三角矩阵三对角矩阵地址的计算

    一维数组的地址计算 设每个元素的大小是size,首元素的地址是a[1],则 a[i] = a[1] + (i-1)*size 若首元素的地址是a[0] 则a[i] = a[0] + i*size 二维 ...

  2. 数据结构---线性表的静态/动态分配与顺序/链式存储

    线性表---基于严魏敏版数据结构c语言实现---谭浩强版c语言 数据元素在计算机中的存储分为顺序存储和链式存储 顺序存储:借助元素在存储器中的相对位置来表示数据元素之间的逻辑关系 链式存储:借助指示元 ...

  3. 图的链式存储结构解析(邻接表、逆邻接表、十字链表、邻接多重表)

    图的矩阵表示法比较消耗空间,需要花费$ n 2 n^2 n2$个单元存储边(弧).在边数较少的情况下比较浪费.我们这里来讨论图的链式存储结构. 图的链式结构主要有四类:邻接表.逆邻接表.十字链表.邻接 ...

  4. 用邻接表存储图c语言,邻接表、邻接多重表、十字链表及C语言实现

    上一节介绍了如何使用顺序存储结构存储邻接多重表和 邻接的意思是顶点之间有边或者弧存在,通过当前顶点,可以直接找到下一个顶点. 邻接表 使用邻接表存储图时,对于图中的每一个顶点和它相关的邻接点,都存储到 ...

  5. 十字链表 java_十字链表法,十字链表压缩存储稀疏矩阵详解

    对于压缩存储稀疏矩阵,无论是使用三元组顺序表,还是使用行逻辑链接的顺序表,归根结底是使用数组存储稀疏矩阵.介于数组 "不利于插入和删除数据" 的特点,以上两种压缩存储方式都不适合解 ...

  6. 十字链表法,十字链表压缩存储稀疏矩阵详解

    对于压缩存储稀疏矩阵,无论是使用三元组顺序表,还是使用行逻辑链接的顺序表,归根结底是使用数组存储稀疏矩阵.介于数组 "不利于插入和删除数据" 的特点,以上两种压缩存储方式都不适合解 ...

  7. 【数据结构】图的存储结构(邻接矩阵、邻接表、十字链表、邻接多重表)及实现(C语言)

    目录 1. 邻接矩阵表示法 1.1 图的邻接矩阵 1.2 创建有向网的邻接矩阵 2. 邻接表表示法 2.1 图的邻接表存储结构 2.2 创建有向图的邻接表 3. 十字链表表示法 3.1 图的十字链表存 ...

  8. 数据结构与算法(6-2)二叉树的存储结构(顺序存储、链式存储)

    目录 一.二叉树的顺序存储 存储方式 总代码 二.二叉树的链式存储(二叉链表) 1.存储结构 2.创建二叉树 总代码 一.二叉树的顺序存储 存储方式 //树的顺序存储 typedef struct { ...

  9. 数据结构第六篇——顺序存储结构与链式存储结构的特点

    ♥注:未经博主同意,不得转载. 两者特点: 顺序表的特点是逻辑上相邻的数据元素,物理存储位置也相邻,并且,顺序表的存储空间需要预先分配. 它的优点: (1)方法简单,各种高级语言中都有数组,容易实现. ...

最新文章

  1. 局部加权线性回归(Local Weighted Linear Regression)+局部加权回归+局部线性回归
  2. 听完411头猪的哼哼,他们找到了理解“猪语”的算法 | Scientific Reports
  3. 八十、 Springboot整合异步任务和定时任务
  4. yum php 降级 5.3,CentOS 5.3 通过yum升级php的方法
  5. linux服务器和客户端配置,Linux基础教程:YUM服务端与客户端配置步骤
  6. 从键盘上打开 Mac 应用程序的 4 种方法
  7. 组了个视频号的局,汇报下数据!
  8. c# 声音控制(转载)
  9. QQ 空间分享报-10001错误 解决
  10. 音乐APP首页框架搭建
  11. 新视角 | 新形势下工厂设备管理的5大误区
  12. 2023年全国最新会计专业技术资格精选真题及答案15
  13. 艾美捷人免疫球蛋白IgG4 ELISA试剂盒,双抗体“三明治”技术
  14. Aconvert 文档格式转换-PDF转免费转其他文档网址-免费
  15. 能够创建时间循环并飞檐走壁的 VR 游戏 TRANSPOSE正式上线
  16. 常用算法的算法思想以及基本特征
  17. 在cmd命令窗口安装Python模块
  18. 快播“洗白”,难道要抛弃用户?
  19. ISP——DPC(Defective Pixel Correction)
  20. 南京农业大学计算机博士几年毕业,通知 | 南京农业大学关于调整博士研究生基本学制及增加博士生培养环节要求的通知...

热门文章

  1. javaScript中createElement案例
  2. Android开发艺术探索全面解读
  3. 大华摄像头webplugin.exe插件开发(需要设置固定IP地址,端口号)
  4. AV(反病毒)技术的演进与规律思索观后感
  5. 基于springboot开发的停车场管理系统
  6. 40个提升自己编程能力的小技巧
  7. 新手必备,教你如何快速绘制出采购流程图?
  8. 计算机人工智能的应用论文,人工智能的发展与应用论文整理.doc
  9. 【备忘】PROFILE
  10. 关于VESA的一些简单介绍