当前位置: 首页 > news >正文

北京专业网站制作价格网站快速收录入口

北京专业网站制作价格,网站快速收录入口,dns 本地 网站建设,深圳福田区住房和建设局网站官网🎇【数据结构】特殊矩阵的压缩存储🎇 🌈 自在飞花轻似梦,无边丝雨细如愁 🌈 🌟 正式开始学习数据结构啦~此专栏作为学习过程中的记录🌟 文章目录 🎇【数据结构】特殊矩阵的压缩存储&#x1f38…

🎇【数据结构】特殊矩阵的压缩存储🎇


🌈 自在飞花轻似梦,无边丝雨细如愁 🌈

在这里插入图片描述


🌟 正式开始学习数据结构啦~此专栏作为学习过程中的记录🌟


文章目录

  • 🎇【数据结构】特殊矩阵的压缩存储🎇
  • 🍰一.数组的存储结构
    • 🚀1.数组的定义
    • 🚀2.数组的存储结构
  • 🍰二.特殊矩阵的存储结构
    • 🚀1.普通矩阵的存储
    • 🚀2.特殊矩阵的压缩存储
      • 🔆1.对称矩阵
      • 🔆2.三角矩阵
      • 🔆3.三对角矩阵
      • 🔆4.稀疏矩阵

🍰一.数组的存储结构

🚀1.数组的定义

数组是由n个相同类型的数据元素所构成的有限序列

数组和线性表的关系:
数组是线性表的推广:一维数组可以看做是一个线性表,而对于二维数组而言,可以看成是有多个线性表组成的线性表

也就是每一行 / / /列视都为一个线性表,总的线性表内每一个元素也是一个定长的线性表

在这里插入图片描述


🚀2.数组的存储结构

  1. 对于一维数组的存储,就是线性表,一维数组的所有元素在内存空间中占用一段连续的内存空间

在这里插入图片描述


那么,对于多维数组的存储,在计算机中是如何实现的呢?

  1. 对于多维数组的存储,在计算机中仍表现为一维数组的形式,也就是一段连续的内存空间
    在这里插入图片描述

接下来,我们就要去尝试模拟计算机存放多维数组的过程:


有两种映射方式:行优先和列优先

①行优先:

以二维数组为例,以行优先存储的方式为:也就是逐行放入一维数组中
在这里插入图片描述

🌈 下标转换关系:

(我们默认下标从0开始)对于二维数组 A [ N ] [ M ] A[N][M] A[N][M] 中的元素 a i j a_{ij} aij ,若希望在行优先转化后的一维数组中访问它,我们可以确定其在一维数组中的下标为:

k = i ∗ M + j k=i*M+j k=iM+j


分解代码实现:

  1. 行优先二维转一维数组
void row_Reducedim(int a[][M],int *res, int row, int col)
{int p = 0;for (int i = 0; i < row; i++) {for (int j = 0; j < col; j++) {res[p++] = a[i][j];}}
}

  1. 按照索引从一维数组中取值
void visit(int res[], int i, int j)
{if (i <= N-1 && i >= 0 && j >= 0 && j <= M-1){int k = i * M + j;cout << res[k] << endl;}elsecout << "输入违规" << endl;
}

行优先完整代码实现:

#include<iostream>
using namespace std;void row_Reducedim(int a[][4],int *res, int row, int col)
{int p = 0;for (int i = 0; i < row; i++) {for (int j = 0; j < col; j++) {res[p++] = a[i][j];}}
}void Print(int a[], int n)
{for (int i = 0; i < n; i++){cout << a[i] << " ";}cout << endl;
}void visit(int res[], int i, int j)
{if (i <= 1 && i >= 0 && j >= 0 && j <= 3){int k = i * 4 + j;cout << res[k] << endl;}elsecout << "输入违规" << endl;
}int main() {int martix[2][4] ={ {1,2,3,4},{5,6,7,8} };int res[8];//二维转一维row_Reducedim(martix,res, 2, 4); //行优先cout << "行转化后的一维数组为:" << endl;Print(res,8);//二维数组元素在一维数组内的映射int i, j;cout << "对于行转换后的矩阵,输入要访问的元素在二维数组中的行,列下标数(>=0)" << endl;cin >> i >> j;visit(res, i, j);system("pause");return 0;
}


②列优先:

以二维数组为例,以行优先存储的方式为:也就是逐列放入一维数组中

🌈 下标转换关系:

对于二维数组 A [ N ] [ M ] A[N][M] A[N][M] 中的元素 a i j a_{ij} aij ,其在一维数组中的下标为:

k = j ∗ N + i k=j*N+i k=jN+i


分解代码实现:

  1. 列优先二维转一维数组
void col_Reducedim(int a[][4], int* res1, int row, int col)
{int p = 0;for (int j = 0; j < col; j++) {for (int i = 0; i < row; i++) {res1[p++] = a[i][j];}}
}

  1. 按照索引从一维数组中取值
void visit1(int res[], int i, int j)
{if (i <= 1 && i >= 0 && j >= 0 && j <= 3){int k = j * 2 + i;cout << res[k] << endl;}elsecout << "输入违规" << endl;
}

列优先完整代码实现:

#include<iostream>
using namespace std;void col_Reducedim(int a[][4], int* res1, int row, int col)
{int p = 0;for (int j = 0; j < col; j++) {for (int i = 0; i < row; i++) {res1[p++] = a[i][j];}}
}void Print(int a[], int n)
{for (int i = 0; i < n; i++){cout << a[i] << " ";}cout << endl;
}void visit1(int res[], int i, int j)
{if (i <= 1 && i >= 0 && j >= 0 && j <= 3){int k = j * 2 + i;cout << res[k] << endl;}elsecout << "输入违规" << endl;
}int main() {int martix[2][4] ={ {1,2,3,4},{5,6,7,8} };int res1[8];//二维转一维col_Reducedim(martix, res1, 2, 4); //列优先cout << "列转化后的一维数组为:" << endl;Print(res1, 8);int a, b;cout << "对于列转换后的矩阵,输入要访问的元素在二维数组中的行,列下标数(>=0)" << endl;cin >> a >> b;visit1(res1, a, b);system("pause");return 0;
}

输出结果:

在这里插入图片描述



🍰二.特殊矩阵的存储结构

🚀1.普通矩阵的存储

对于普通的矩阵,我们可以将其视为二维数组进行处理,也就是按行优先和列优先的方式存储,在之前也已经提到过

在这里插入图片描述


🚀2.特殊矩阵的压缩存储

压缩存储:指为多个值相同的元素所分配一个存储空间,对零元素不分配存储空间,用于节省空间

接下来,我们来看几个典型的特殊矩阵:

🔆1.对称矩阵

对于一个n阶的方阵,我们可以将其划分为主对角线,上三角区和下三角区,而对于对称矩阵来说,有 a i j = a j i a_{ij}=a_{ji} aij=aji,因此,若仍然采用二维数组存储,会造成一半的空间浪费

策略:

因此,我们其实只需要 存主对角线和下三角块 即可:
在这里插入图片描述


🌊 对称矩阵与存储后一维数组的映射关系:

我们规定矩阵元素的下标 i , j i,j ij的范围为 [ 1 , n ] [1,n] [1,n],而一维数组的下标默认是从0开始的

在这里插入图片描述

  1. 一维数组大小:
    第一行:一个元素, a 11 a_{11} a11
    第二行:两个元素, a 21 , a 22 a_{21},a_{22} a21,a22

    共有 n n n 行,则元素总数 k = n ∗ ( n + 1 ) / 2 k=n*(n+1)/2 k=n(n+1)/2

在这里插入图片描述


  1. 压缩存储后的访问:

    又回到了,压缩完成之后,我们应该如何获取这些数据呢?

    我们只需要定义一个映射函数即可:

在这里插入图片描述

策略:

不难发现,如果我们希望取出二维数组内的元素 a i j a_{ij} aij,我们已知了它的行号和列号:

①先看行向:
a i j a_{ij} aij上面的元素(即前 i − 1 i-1 i1行)的元素个数为:

i ∗ ( i − 1 ) / 2 i*(i-1)/2 i(i1)/2

②再看列向:
a i j a_{ij} aij前面的元素(即前 j − 1 j-1 j1行)的元素个数为:

j − 1 j-1 j1


由于一维数组下标是从 0 0 0开始的,因此: a i j 的一维数组下标 = 在 a i j 前的元素个数 a_{ij}的一维数组下标=在a_{ij}前的元素个数 aij的一维数组下标=aij前的元素个数

再由 a i j = a j i a_{ij}=a_{ji} aij=aji,因此,映射函数为:

在这里插入图片描述


完整代码实现:

#include<iostream>
using namespace std;//打印下三角
void triangle(int a[][3], int* res, int row, int col)
{int p = 0;for (int i = 0; i < row; i++) {for (int j = 0; j < col; j++) {if (i >= j)res[p++] = a[i][j];}}
}//访问
void visit(int res[], int i, int j)
{if (i >= j){int k = i * (i - 1) / 2 + j - 1;cout << res[k] << endl;}else{int k = j * (j - 1) / 2 + i - 1;cout << res[k] << endl;}
}//打印一维数组
void Print(int a[], int n)
{for (int i = 0; i < n; i++){cout << a[i] << " ";}cout << endl;
}int main() {int martix[3][3] ={	{1,2,3},{2,1,2},{3,2,1} };int res[6];triangle(martix, res, 3, 3);cout << "下三角的一维数组为:" << endl;Print(res,6);int i, j;cout << "请输入需要访问的元素aij中的下标i,j(>=1):" << endl;cin >> i >> j;visit(res, i, j);system("pause");return 0;
}

输出结果:

在这里插入图片描述


🔆2.三角矩阵

三角矩阵就是有一个三角区全为常量的矩阵

在这里插入图片描述


策略:

其储存思维和对称矩阵类似,不同之处就在于:

存储完下三角区和主对角线后,紧接着存储对角线上方的常量,也就是要在对称矩阵构造的一维数组后面添加一个常数项

在这里插入图片描述


  1. 一维数组的大小:

    k = n ∗ ( n + 1 ) / 2 k=n*(n+1)/2 k=n(n+1)/2

  2. 映射函数为:

在这里插入图片描述


完整代码实现:

#include<iostream>
using namespace std;//打印下三角
void triangle(int a[][3], int* res, int row, int col,int n)
{int p = 0;for (int i = 0; i < row; i++) {for (int j = 0; j < col; j++) {if (i >= j)res[p++] = a[i][j];}}//存常量int c = a[0][n-1];res[n * (n + 1) / 2] = c;
}//访问
void visit(int res[], int i, int j,int n)
{if (i >= j){int k = i * (i - 1) / 2 + j - 1;cout << res[k] << endl;}else{int k = n * (n + 1)/2;cout << res[k] << endl;}
}//打印一维数组
void Print(int a[], int n)
{for (int i = 0; i < n; i++){cout << a[i] << " ";}cout << endl;
}int main() {int martix[3][3] ={ {1,4,4},{2,1,4},{3,2,1} };int res[6];triangle(martix, res, 3, 3,3);cout << "下三角的一维数组为:" << endl;//加一个常数项Print(res, 6+1);int i, j;cout << "请输入需要访问的元素aij中的下标i,j(>=1):" << endl;cin >> i >> j;visit(res, i, j,3);system("pause");return 0;
}

输出结果:

在这里插入图片描述


🔆3.三对角矩阵

三对角矩阵也称带状矩阵,对于n阶方阵的A中的任一元素 a i j a_{ij} aij,当 ∣ i − j ∣ > 1 |i-j|>1 ij>1时, a i j = 0 a_{ij}=0 aij=0

在这里插入图片描述


策略:

将三条对角线上的元素按行优先原则存放在一维数组中(零元素不存)

在这里插入图片描述


  1. 一维数组的大小:
    由于只有第一行和最后一行只有两个元素,因此,一维数组大小为:

    l e n = 3 n − 2 len=3n-2 len=3n2

  2. 映射函数为:
    由于前 i − 1 i-1 i1行有 3 i − 1 3i-1 3i1个元素,当前行前面有 j − i + 1 j-i+1 ji+1个元素

    k = 2 i + j − 3 k=2i+j-3 k=2i+j3


反之,若我们已知 a i j a_{ij} aij存放于一维数组中的第 k个位置,怎么推出行数和列数呢?

在这里插入图片描述


i = ⌈ ( k + 2 ) / 3 ⌉ i=⌈(k+2)/3⌉ i=⌈(k+2)/3 再由公式 k = 2 i + j − 3 k=2i+j-3 k=2i+j3可以推出: j = k − 2 i + 3 j=k-2i+3 j=k2i+3


完整代码实现:

#include<iostream>
#include<math.h>
using namespace std;//转一维矩阵
void Three(int a[][4], int* res, int row, int col)
{int p = 0;for (int i = 0; i < row; i++) {for (int j = 0; j < col; j++) {if (a[i][j] != 0)res[p++] = a[i][j];}}
}void Print(int a[],int n) {for (int i = 0; i < n; i++) {cout << a[i] << " ";}cout << endl;
}void visit1(int a[], int i, int j)
{int k = 2*i + j - 3;printf("a%d%d=%d\n", i,j,a[k]);
}void visit2(int a[], int k)
{int i, j;i = ceil((k + 2) / 3);j = k - 2 * i + 3;printf("访问的元素为:a%d%d\n", i, j);
}int main() {int martix[4][4] ={{1,2,0,0},{1,2,3,0},{0,2,3,4},{0,0,3,4}};int res[10];//转一维Three(martix, res, 4, 4);cout << "三对角的一维矩阵为:" << endl;Print(res, 10);//正向访问int i, j;cout << "请输入需要访问的元素aij中的下标i,j(>=1):" << endl;cin >> i >> j;visit1(res, i, j);//反向访问int k;cout<<"请输入该元素在一维数组中的下标:" << endl;cin >> k;visit2(res, k);system("pause");return 0;
}

输出结果:

在这里插入图片描述



🔆4.稀疏矩阵

还有一种特殊矩阵,其矩阵内的非0元素远远少于零元素,则称其为稀疏矩阵

e . g e.g e.g 如下矩阵:
在这里插入图片描述

我们只存取非零元素,但其分布往往没有规律,因此,我们还应该记录它的位置

策略:

将非零元素的行,列,值构成一个三元组 (行标,列标,值) (行标,列标,值) (行标,列标,值)

我们用结构体定义这个三元组:

#define Maxsize 100//结构体定义三元组
typedef struct {int i;int j;int val;
}Triple[Maxsize]; //结构体数组

在这里插入图片描述


完整代码实现:

#include<iostream>
#define Maxsize 100
using namespace std;//结构体定义三元组
typedef struct {int i;int j;int val;
}Triple[Maxsize]; //结构体数组//稀疏矩阵转三元组
void triple(Triple &T,int a[][5],int row,int col,int &p)
{for (int i = 0; i < row; i++) {for (int j = 0; j < col; j++) {if (a[i][j] != 0) {T[p].i = i+1;T[p].j = j+1;T[p].val = a[i][j];p++;}}}
}void Print(Triple &T,int len) {for (int i = 0; i < len; i++) {printf("a%d%d=",T[i].i,T[i].j);cout << T[i].i<< " " << T[i].j << " " << T[i].val << endl;}
}int main() {int martix[5][5] ={{0,2,0,0,0},{0,0,1,0,2},{3,0,0,0,1},{0,5,0,0,0},{1,0,4,0,0}};Triple T;int p = 0;//稀疏矩阵转三元组triple(T, martix, 5, 5, p);cout << "转化后的三元组为(矩阵元素下标从1开始):\n" << endl;Print(T, p);system("pause");return 0;
}

输出结果:

在这里插入图片描述


🎇本节详细讲解了数组相关操作及各种特殊矩阵的压缩存储方式~🎇

如有错误,欢迎指正~!


在这里插入图片描述

在这里插入图片描述


文章转载自:
http://sullage.rpwm.cn
http://unleash.rpwm.cn
http://shekinah.rpwm.cn
http://noumenon.rpwm.cn
http://unrevealed.rpwm.cn
http://nursling.rpwm.cn
http://aic.rpwm.cn
http://chutzpa.rpwm.cn
http://mohism.rpwm.cn
http://mantlet.rpwm.cn
http://stockman.rpwm.cn
http://levoglucose.rpwm.cn
http://cowtail.rpwm.cn
http://granuloblast.rpwm.cn
http://prostie.rpwm.cn
http://wiring.rpwm.cn
http://retainer.rpwm.cn
http://reembark.rpwm.cn
http://lymphoblastic.rpwm.cn
http://haulageway.rpwm.cn
http://show.rpwm.cn
http://honolulu.rpwm.cn
http://indevotion.rpwm.cn
http://terror.rpwm.cn
http://filibeg.rpwm.cn
http://spontaneous.rpwm.cn
http://fibrovascular.rpwm.cn
http://fond.rpwm.cn
http://linograph.rpwm.cn
http://salicetum.rpwm.cn
http://rasp.rpwm.cn
http://ngaio.rpwm.cn
http://delighted.rpwm.cn
http://remuneration.rpwm.cn
http://calcimine.rpwm.cn
http://diazonium.rpwm.cn
http://unhealthily.rpwm.cn
http://emotively.rpwm.cn
http://obsequious.rpwm.cn
http://causality.rpwm.cn
http://provocative.rpwm.cn
http://vicugna.rpwm.cn
http://gyroscope.rpwm.cn
http://id.rpwm.cn
http://ether.rpwm.cn
http://moider.rpwm.cn
http://dubiously.rpwm.cn
http://alfaqui.rpwm.cn
http://galling.rpwm.cn
http://vidicon.rpwm.cn
http://assessor.rpwm.cn
http://kefir.rpwm.cn
http://dumb.rpwm.cn
http://upbow.rpwm.cn
http://immunodepression.rpwm.cn
http://deadlatch.rpwm.cn
http://cylinder.rpwm.cn
http://leishmanial.rpwm.cn
http://galvanometrically.rpwm.cn
http://flushing.rpwm.cn
http://hydrogenisation.rpwm.cn
http://batholithic.rpwm.cn
http://ligase.rpwm.cn
http://doxepin.rpwm.cn
http://rosemary.rpwm.cn
http://masscult.rpwm.cn
http://gargouillade.rpwm.cn
http://foram.rpwm.cn
http://enflurane.rpwm.cn
http://unbiased.rpwm.cn
http://chellean.rpwm.cn
http://nevis.rpwm.cn
http://polymorph.rpwm.cn
http://verbalization.rpwm.cn
http://plink.rpwm.cn
http://carbonade.rpwm.cn
http://gama.rpwm.cn
http://coastward.rpwm.cn
http://hussy.rpwm.cn
http://region.rpwm.cn
http://antipodean.rpwm.cn
http://sbw.rpwm.cn
http://tracheate.rpwm.cn
http://squarish.rpwm.cn
http://amoebean.rpwm.cn
http://pilary.rpwm.cn
http://jesting.rpwm.cn
http://whimling.rpwm.cn
http://bullbaiting.rpwm.cn
http://marse.rpwm.cn
http://brandade.rpwm.cn
http://bankroll.rpwm.cn
http://phosphorus.rpwm.cn
http://mississippian.rpwm.cn
http://grigri.rpwm.cn
http://sciolism.rpwm.cn
http://weeds.rpwm.cn
http://anaerophyte.rpwm.cn
http://brigand.rpwm.cn
http://vacuolating.rpwm.cn
http://www.15wanjia.com/news/64451.html

相关文章:

  • 哪个网站做分享赚佣金厦门人才网个人登录
  • 做网站需要什么手续资料推广一般收多少钱
  • 做快餐 承包食堂的公司网站外贸推广平台怎么做
  • title:(网站开发)线上推广策划方案范文
  • 美食网站页面设计模板网站营销策略
  • 2015年做那些网站致富百度快照手机入口
  • 淮安公司做网站推广引流
  • 舟山网站建设公司宁波seo优化定制
  • 徐州建站公司哪家好百度首页精简版
  • 创作网站西安做网页的公司
  • 安徽省建设造价管理协会网站被公司优化掉是什么意思
  • 网站搬家seo营销型网站策划
  • 兰州网络公司网站怎么做百度推广
  • 网站怎么做单页电商平台推广公司
  • 直播引流推广方法seo公司是做什么的
  • 甘肃做网站的公司河南百度seo
  • wordpress文章列表seo搜索引擎优化公司
  • 门户网站案例如何做电商新手入门
  • 建设部网站的诚信平台国内seo公司排名
  • 餐饮平台app有哪些网站关键词推广优化
  • wordpress 切换语言槐荫区网络营销seo
  • 建设厅国网查询网站合肥百度seo代理
  • 网站建设发票 税率广告推广免费
  • .net电商网站全站开发江东怎样优化seo
  • 网站三级页怎么做抖音seo怎么做
  • 驻马店app和网站开发公司seo营销培训
  • 国际新闻今天最新消息自己怎么做网站优化
  • 沈阳关键词seo深圳seo优化
  • 做微商网站需要哪些seo对网店推广的作用
  • 新网网站后台登陆3分钟搞定网站seo优化外链建设