前言

此文章是本人第一篇博客,目的在于巩固过去所学的知识,同时可能会给大家带来一丝丝帮助,但由于没有经验加上本人能力极其有限,文章中可能存在不足之处,还请读者能够指正(`・ω・´)。

这篇文章首先会介绍矩阵压缩存储和特殊矩阵的基本概念,然后将会比较详细地说明几种特殊的矩阵:对称矩阵、三角矩阵、带状矩阵(三对角矩阵)、稀疏矩阵的压缩存储的策略,包括定量计算和十字链表的c语言代码和效果图,让我们开始吧!

注意,本文所用数组下标均为从0开始

正文

一.基本概念

压缩存储

在一个矩阵中,若多个数据的值相同,为了节省内存空间,则只分配一个元素值的空间,且零元素不占存储空间

特殊矩阵

可不是所有的矩阵都适合压缩存储!比如下面这个

1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16

下面介绍的几个特殊矩阵,才是将要重点介绍的对象:

1.对称矩阵

对称矩阵是指元素以主对角线为对称轴对应相等的n阶矩阵,即aᵢ,ⱼ=aⱼ,ᵢ

比如

5 1 2 3 4
1 5 6 7 8
2 6 5 9 10
3 7 9 5 12
4 8 10 12 5

2.三角矩阵

三角矩阵是方阵的一种,分为上三角矩阵和下三角矩阵,上三角矩阵是指下三角区所有元素均为同一常量,下三角矩阵是指上三角区所有元素均为同一常量

上三角矩阵

下三角矩阵

 3.带状矩阵(三对角矩阵)

带状矩阵指所有非零元素都集中在以主对角线为中心的3条对角线的区域,其他区域均为零的矩阵特点:当|i-j|>1时,有aᵢ,ⱼ=0  或者说主对角线的相邻的上下左右元素可以是非0元素,再往外肯定是0元素的矩阵

如下图所示:

带状矩阵

4.稀疏矩阵 

在矩阵中,若数值为0的元素数目远远多于非0元素的数目,并且非0元素分布没有规律时,则称该矩阵为稀疏矩阵,但是对于这个“远远多于”并没有准确的定量规定。

比如

稀疏矩阵的例子

行优先与列优先   映射

对于一个二维数组,外观上看是一个矩阵,但是电脑内存是线性存储的,所以电脑会自动按照一定的规则,去把二维数组转换为地址连续的块放到内存中,这些规则分为行优先和列优先

比如下面这个矩阵

1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16

如果按行优先,放到内存就是1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

列优先就是1 5 9 13 2 6 10 14 3 7 11 15 4 8 12 16

我们在矩阵的压缩存储中,通常的策略就是把二维矩阵通过一定的下标(i,j)的映射规则放入到一维数组中,比如说呢,下面这个对称矩阵

2 4
4 2

放到一维数组a中只需包含 2 4,分别为a[0]和a[1],数组的下标0与1与矩阵Ai,j的元素下标i和j的关系就是所谓的映射,这也是定量计算的重点!

二.特殊矩阵存储策略

1.对称矩阵

设有对称矩阵A[i][j]如下图:(aᵢ,ⱼ=aⱼ,ᵢ )

存储策略:只存储主对角线+下三角区(或主对角线+上三角区),以主对角线+下三角区为例,按照行优先把这些元素放入到一维数组中,就得到了下面的样子的一维数组:

a₁₁ a₂₁ a₂₂ a₃₁ ... aₙ,ₙ₋₂ aₙ,ₙ₋₁ aₙ,ₙ

这个一维数组的大小是1+2+3+...+n=n*n(n+1)/2

下面来把行号和列号转换为数组下标:

aᵢ,ⱼ是第i行的元素,所以前面还有i-1行,元素总数为1+2+...+i-1=i*(i-1)/2

j代表其属于第j列,所以最终确定按照行优先的存储aᵢ,ⱼ应该在一维数组的第i*(i-1)/2+j个位置,但是由于数组是从0开始存的,所以对应下标为i*(i-1)/2+j-1

上述讨论的均为在下三角区的情形,此时i>=j

现在根据性质aᵢ,ⱼ=aⱼ,ᵢ可以得到矩阵所有元素与一维数组下标k的对应关系如下:

2.三角矩阵

给出下面的下三角矩阵A[i][j]

存储策略:按照行优先将下三角区域(橙色部分)放入一位数组中,并将常数c放到最后一个位置

得到下图的一位数组

a₁₁ a₂₁ a₂₂ a₃₁ ... aₙ,ₙ₋₁ aₙ,ₙ c

这个一位数组的大小为:1+2+3+...+n+1=n*n(n+1)/2+1

这个映射关系和对称矩阵几乎一样,唯一不同的是当i<j,即取上三角的元素时,都得到存在一维数组最后一个位置的常数c,如下图

再来看上三角矩阵

给出下面的上三角矩阵A[i][j]

可以按照行优先原则,把上三角区域的元素(绿色区域),放入一位数组中,并在最后一个位置放入常数c,即可得到下面的一维数组

a₁₁ a₁₂ a₁₃ ... a₁,ₙ ... aₙ,ₙ c

这个的数组大小与下三角的一样,对于一个元素aᵢ,ⱼ,第i行的元素要存n-i+1个元素,第i-1行要存n-i+2个元素,所以前i-1行的元素总数为n+n-1+...+n-i+2,由于在第j列,所以对应第i行的第j-i+1个元素,总的来说,就是数组中的第n+n-1+...+n-i+2+j-i+1个元素,在数组中下标从0开始所以为n+n-1+...+n-i+2+j-i

综上,可以得到如下的映射关系

3.带状矩阵

给出下面的带状矩阵A[i][j]

存储策略,按照行优先的原则,只存储带状部分,便可以得到下面的一维数组:

a₁₁ a₁₂ a₂₁ a₂₂ ... aₙ₋₁,ₙ aₙ,ₙ₋₁ aₙ,ₙ

先计算一维数组的大小,每行三个元素,共n行,3*n,但第一行和最后一行仅仅2个元素,所以总共个数为3*n-2

下面研究映射关系:

当|i-j|>1时,值就是0

当当|i-j|<=1时,对于一个元素aᵢ,ⱼ,前i-1行,每行有三个,第一行少了一个,总共为3*(i-1)-1个元素,而且找规律可以知道,这个元素在第i行是第j-i+2个元素,所以总共是数组的第3*(i-1)-1+j-i+2个元素即第2*i+j-2个元素,对应数组下标为2*i+j-3

所以映射关系为

下面再来探讨一个逆问题,就是如果给出数组下标k,想要得到这个元素在第几行第几列怎么办呢?

首先,这个元素是第k+1个元素,假设它在第i行第j列,那么前i-1行元素总数为3*(i-1)-1,前i行元素总数为3*i-1,满足下面的不等式

3*(i-1)-1<k+1<=3*i-1

解得:i>=(k+2)/3

为了让这个i“刚好大于(k+2)/3”,让其向上取整,即i=⌈(k+2)/3⌉(提示:⌈⌉是向上取整,⌊⌋是向下取整)

然后再根据我们上面得出的关系式:k=2*i+j-3综合可得j的值,从而得到i和j即为元素行数和列数

4.稀疏矩阵

给出下面这个稀疏矩阵

给出两个方法去存储它

第一个方式是顺序存储,通过一个包含行号、列号、元素值的三元组,去进行存储,比如这个矩阵,我们可以用三元组表示为:

行数  i 列数  j 值  v
1 3 4
1 6 5
2 2 3
2 4 9
3 5 7
4 2 2

可以定义包括i j v 的结构体数组

第二个方法是链式存储的十字链表法

可以表示为下图:

对于每一个非0元素的结点,包含3个数据域行数i、列数j、元素值v,和两个指针域,左边的指针指向同列的下一个元素,右边的指针指向同行的下一个元素

下面给出十字链表的c语言实现代码以及效果图,如果代码有不足之处,可以指出!:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define OVERFLOW -1
#define OK 1
typedef  int ElemType;
typedef  int Status;
typedef struct OLNode{int i,j;ElemType e;struct OLNode *right,*down;
}OLNode,*OLink;
typedef struct {OLink *rhead,*chead; //行和列链表头指针向量基地址由CreatSMatrix分配 int mu,nu,tu;//稀疏矩阵行数,列数和非0元素个数
}CrossList,*CrossListPtr; Status CreatSMatrix_OL (CrossListPtr M)
{//创建稀疏矩阵M,采用十字链表存储表示if(M) free(M);//释放M原有的内存M=(CrossListPtr)malloc(sizeof(CrossList));int m,n,t,a;int i,j,e;int cnt; OLNode *p,*q;printf("请分别输入行数,列数,非零元素的个数:");scanf("%d%d%d",&m,&n,&t);//输入M的行数列数和非零元素个数M->mu=m;M->nu=n;M->tu=t;//赋到M里面if(!(M->rhead=(OLink *)malloc((m+1)*sizeof(OLink)))) exit(OVERFLOW);if(!(M->chead=(OLink *)malloc((n+1)*sizeof(OLink)))) exit(OVERFLOW);//分别为行链表头和列链表头分配内存for(a=1;a<=m;a++) M->rhead[a]=NULL;for(a=1;a<=n;a++) M->chead[a]=NULL;//使各行列链表都为空表for(cnt=1;cnt<=t;cnt++)//按任意次序输入非0元素,{printf("请分别输入第%d个元素的行数,列数和值:",cnt);scanf("%d%d%d",&i,&j,&e);if(!(p=(OLNode *)malloc(sizeof(OLNode)))) exit(OVERFLOW);p->i=i;p->j=j;p->e=e;//生成结点if(M->rhead[i]==NULL||M->rhead[i]->j>j) {p->right=M->rhead[i]; M->rhead[i]=p;} //如果行链表数组的第i行的头结点右边是空或者右边元素的列数比j大,让p左边被链表的rhead指针指住else{for(q=M->rhead[i];(q->right)&&q->right->j<j;q=q->right);//找到将要插入的合适位置,要么是右边为空,要么q->right->j<jp->right=q->right;q->right=p;//插入 } //行插入 if(M->chead[j]==NULL||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;}//列插入 } //下面检验是否存储成功 int check[10][10];memset(check,0,sizeof(check));int i1,j1;OLink p1;for(i1=1;i1<=M->mu;i1++){for(p1=M->rhead[i1];p1;p1=p1->right){check[i1][p1->j]=p1->e;}  } for(i1=1;i1<=M->mu;i1++){for(j1=1;j1<=M->nu;j1++){printf("%d ",check[i1][j1]);} printf("\n");}return OK;
}
int main()
{CrossListPtr M=NULL;CreatSMatrix_OL(M);return 0;
}

这是效果图:

今天的文章就到这里了(`・ω・´)

特殊矩阵的压缩存储(详细版 通俗易懂 含c语言稀疏矩阵十字链表代码 )相关推荐

  1. 5.3矩阵的压缩存储(稀疏矩阵转置和快速转置)

    在矩阵中有许多值相同的元素或者是零元素.有时为了节省存储空间,可以对这类矩阵进行压缩存储.所谓的压缩存储是指:为多个值相同的元值分配一个存储空间:对零元不分配空间. 5.32稀疏矩阵 在m*n的矩阵中 ...

  2. 数据结构笔记(十七)--矩阵的压缩存储

    矩阵的压缩存储 一.矩阵的分类 1.特殊矩阵:其矩阵值在在矩阵中分布有规律 2.稀疏矩阵:矩阵的非零值在矩阵中占比小于0.05的矩阵,即零值占比在95%以上 3.一般矩阵:不属于上面的两种矩阵 二.矩 ...

  3. 数据结构的学习_4.2 矩阵的压缩存储(对称矩阵)

    4.2 矩阵的压缩存储(一) 在有些情况下,矩阵中含有许多值相同或者值为零的元素,如果还按前面的方法来存储这种矩阵,就会产生大量的空间浪费.为了节省存储空间,可以对这类矩阵采用压缩存储. 4.2.1 ...

  4. 矩阵的压缩存储(随机稀疏矩阵的建立和输出)

    实际应用中会有很多利用高阶矩阵的问题,有的高阶矩阵已达到几十万阶,几千亿个元素.然而,多数的高阶矩阵中包含了大量的数值为零的元素,需要对这类矩阵进行压缩存储.因为合理的压缩存储不仅能有效地节省存储空间 ...

  5. 9.特殊矩阵的压缩存储

    压缩存储:指多个值相同的元素只分配一个存储空间, 对零元素不分配存储空间. 特殊矩阵:指具有许多相同矩阵元素或零元素,并且这些相同矩阵元素或零元素的 分布有一定规律性的矩阵. 特殊矩阵的压缩存储:找出 ...

  6. 34-对称矩阵的压缩存储

    对于矩阵这样由n行n列构成的数据集合,可以通过二维数组来进行存储. 在实际工程中也会用到一些特殊的矩阵, 特殊矩阵可以"压缩"的一种思维来降低空间需求. (1)对角矩阵 (2)对称 ...

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

    特殊矩阵的压缩存储 压缩存储的定义: 若多个数据元素的值都相同,则只分配一个元素值的存储空间,且 零元素不占存储空间. 能够压缩的一些矩阵: 一些特殊矩阵,如:对称矩阵,对角矩阵,三角矩阵,稀疏矩阵等 ...

  8. 数据结构C语言实现-矩阵的压缩存储

    一.矩阵的压缩存储: 在编写程序时往往都是二维数组表示矩阵,然而在数值分析中经常出现一些阶数很高的的矩阵同时在距震中有很多值相同的元素,或者是零元素,为了节省空间,可以对这类矩阵进行压缩存储,所谓的压 ...

  9. 3~4矩阵的压缩存储(下)【详解】

    目录 一.特殊矩阵的压缩存储 1.数组的定义 1.1概述 1.2数组与线性表的关系 1.3特点 2.数组的存储结构 2.1一个数组 2.2多维数组 二.矩阵的压缩存储 1.概述 1.1压缩存储 1.2 ...

最新文章

  1. 如何使cmd的输入和输出重定向到管道中(用这种方法可以将指令写入cmd并抓取输出)
  2. [unix shell笔记] - 和find命令结合使用xargs命令
  3. 收藏:asp.net
  4. 镜像电流源特点_9000大型地网变频大电流接地特性测量系统介绍
  5. Python之字典类型数据常见操作及排序
  6. 谷歌浏览器78如何安装拓展程序
  7. Pandas知识点-逻辑运算
  8. 7-68 求整数段和 (15 分)
  9. 【网络编程】Socket网络编程基础
  10. 《给QTreeView表项添加CheckBox和图标》:系列教程之七
  11. DeepSORT的改进
  12. 使用VS2015+win7编译WebKit(WebKit-r189384)
  13. 开源软件的安全性风险_认真对待开源安全性
  14. html用于排版标题标签,HTML常用标签(示例代码)
  15. Docker配置mc服务器
  16. 【ReView】 学习日志 from18/11/24 to 19/7/10
  17. 嵌入式C++开发详解
  18. cx_Oracle使用方法
  19. (SVN+SSH)搭建SVN并使用SSH进行免密拉取推送代码
  20. 宿州可以学中专计算机的学校有哪些,2019宿州中职学校名单大全

热门文章

  1. 电大网络计算机绘图,国开电大 计算机绘图(终结性考试)大作业答案
  2. 脑启发重放,利用人工神经网络进行持续学习
  3. python中的模块_Python中的模块 | 萧小寒
  4. OpenAL 3D效果营造
  5. 经典推荐——计算机科学殿堂的知识瑰宝
  6. python接口测试之request请求二(传递参数)
  7. PROE4.0二次开发基视频教程从入门到精通教程
  8. 自然语言处理NLP学习笔记三:使用Django做一个NLP的Web站点
  9. 智慧林业落地入口在林业物联网工程
  10. 【2022吴恩达机器学习】决策树