多维数组与特殊矩阵:存储与压缩

多维数组与特殊矩阵:存储与压缩

一、多维数组的存储

(一)基本概念

多维数组是线性表的推广,例如二维数组可以看作是元素为一维数组的线性表,三维数组可以看作是元素为二维数组的线性表,以此类推。在内存中,多维数组需要按照一定的顺序进行存储,常见的存储方式有行优先存储和列优先存储。

(二)行优先存储

以二维数组为例,行优先存储是先存储第一行的元素,然后再存储第二行的元素,依此类推。对于一个 mn 列的二维数组 a[m][n],其元素 a[i][j] 在内存中的地址计算(假设每个元素占用 k 个字节,数组首地址为 base):
[LOC(a[i][j]) = base + (i * n + j) * k]

(三)列优先存储

列优先存储则是先存储第一列的元素,再存储第二列的元素等。对于上述二维数组,元素 a[i][j] 在列优先存储下的内存地址计算:
[LOC(a[i][j]) = base + (j * m + i) * k]

(四)C 语言示例

以下是一个在 C 语言中对二维数组进行初始化并计算其元素地址的示例:

#include <stdio.h>// 假设元素为 int 类型,每个 int 占 4 个字节
#define ELEMENT_SIZE 4// 计算行优先存储下元素的地址
int rowMajorAddress(int a[][100], int i, int j, int m, int n) {int base = (int)a;return base + (i * n + j) * ELEMENT_SIZE;
}// 计算列优先存储下元素的地址
int colMajorAddress(int a[][100], int i, int j, int m, int n) {int base = (int)a;return base + (j * m + i) * ELEMENT_SIZE;
}int main() {// 声明一个 3 行 4 列的二维数组并初始化int matrix[3][4] = {{1, 2, 3, 4},{5, 6, 7, 8},{9, 10, 11, 12}};// 计算并打印行优先存储下元素 matrix[1][2] 的地址int rowAddr = rowMajorAddress(matrix, 1, 2, 3, 4);printf("行优先存储下 matrix[1][2] 的地址: %d\n", rowAddr);// 计算并打印列优先存储下元素 matrix[1][2] 的地址int colAddr = colMajorAddress(matrix, 1, 2, 3, 4);printf("列优先存储下 matrix[1][2] 的地址: %d\n", colAddr);return 0;
}

二、特殊矩阵的存储与压缩

(一)对称矩阵

  1. 存储特点
    • 对称矩阵是指 a[i][j] = a[j][i] 的矩阵。对于一个 n 阶对称矩阵,我们只需要存储其下三角(或上三角)部分的元素即可,因为根据对称性可以得到另一半元素的值。
  2. 存储方式
    • 可以将下三角部分按行优先存储到一个一维数组 sa 中。对于下三角元素 a[i][j]i >= j),其在一维数组中的下标 k 计算如下:
      [k=\frac{i(i + 1)}{2}+j]
  3. C 语言示例
// 存储对称矩阵的下三角部分到一维数组
void storeSymmetricMatrix(int a[][100], int sa[], int n) {int k = 0;for (int i = 0; i < n; i++) {for (int j = 0; j <= i; j++) {sa[k++] = a[i][j];}}
}// 根据一维数组恢复对称矩阵
void restoreSymmetricMatrix(int a[][100], int sa[], int n) {int k = 0;for (int i = 0; i < n; i++) {for (int j = 0; j <= i; j++) {a[i][j] = sa[k];a[j][i] = sa[k++];}}
}int main() {// 声明一个 4 阶对称矩阵并初始化int symmetricMatrix[4][4] = {{1, 2, 3, 4},{2, 5, 6, 7},{3, 6, 8, 9},{4, 7, 9, 10}};int sa[10];  // 用于存储对称矩阵下三角部分的一维数组// 存储对称矩阵下三角部分storeSymmetricMatrix(symmetricMatrix, sa, 4);// 恢复对称矩阵int restoredMatrix[4][4];restoreSymmetricMatrix(restoredMatrix, sa, 4);// 打印恢复后的对称矩阵,验证正确性for (int i = 0; i < 4; i++) {for (int j = 0; j < 4; j++) {printf("%d ", restoredMatrix[i][j]);}printf("\n");}return 0;
}

(二)三角矩阵

  1. 上三角矩阵
    • 存储特点:上三角矩阵是主对角线以下元素全为 0 的矩阵。对于 n 阶上三角矩阵,我们可以只存储其主对角线及以上的元素。
    • 存储方式:按行优先存储主对角线及以上元素到一维数组 ua 中。对于上三角元素 a[i][j]i <= j),其在一维数组中的下标 k 计算如下:
      [k=\frac{(2n - i - 1)i}{2}+j - i]
    • C 语言示例
// 存储上三角矩阵到一维数组
void storeUpperTriangularMatrix(int a[][100], int ua[], int n) {int k = 0;for (int i = 0; i < n; i++) {for (int j = i; j < n; j++) {ua[k++] = a[i][j];}}
}// 根据一维数组恢复上三角矩阵
void restoreUpperTriangularMatrix(int a[][100], int ua[], int n) {int k = 0;for (int i = 0; i < n; i++) {for (int j = i; j < n; j++) {a[i][j] = ua[k++];if (j > i) {a[j][i] = 0;}}}
}int main() {// 声明一个 4 阶上三角矩阵并初始化int upperTriangularMatrix[4][4] = {{1, 2, 3, 4},{0, 5, 6, 7},{0, 0, 8, 9},{0, 0, 0, 10}};int ua[10];  // 用于存储上三角矩阵的一维数组// 存储上三角矩阵storeUpperTriangularMatrix(upperTriangularMatrix, ua, 4);// 恢复上三角矩阵int restoredUpperMatrix[4][4];restoreUpperTriangularMatrix(restoredUpperMatrix, ua, 4);// 打印恢复后的上三角矩阵,验证正确性for (int i = 0; i < 4; i++) {for (int j = 0; j < 4; j++) {printf("%d ", restoredUpperMatrix[i][j]);}printf("\n");}return 0;
}
  1. 下三角矩阵
    • 存储特点:下三角矩阵是主对角线以上元素全为 0 的矩阵。
    • 存储方式:类似对称矩阵下三角存储,按行优先存储下三角元素到一维数组 la 中。对于下三角元素 a[i][j]i >= j),其在一维数组中的下标 k 计算同对称矩阵下三角元素存储下标计算:
      [k=\frac{i(i + 1)}{2}+j]
    • C 语言示例
// 存储下三角矩阵到一维数组
void storeLowerTriangularMatrix(int a[][100], int la[], int n) {int k = 0;for (int i = 0; i < n; i++) {for (int j = 0; j <= i; j++) {la[k++] = a[i][j];}}
}// 根据一维数组恢复下三角矩阵
void restoreLowerTriangularMatrix(int a[][100], int la[], int n) {int k = 0;for (int i = 0; i < n; i++) {for (int j = 0; j <= i; j++) {a[i][j] = la[k++];if (j < i) {a[j][i] = 0;}}}
}int main() {// 声明一个 4 阶下三角矩阵并初始化int lowerTriangularMatrix[4][4] = {{1, 0, 0, 0},{2, 5, 0, 0},{3, 6, 8, 0},{4, 7, 9, 10}};int la[10];  // 用于存储下三角矩阵的一维数组// 存储下三角矩阵storeLowerTriangularMatrix(lowerTriangularMatrix, la, 4);// 恢复下三角矩阵int restoredLowerMatrix[4][4];restoreLowerTriangularMatrix(restoredLowerMatrix, la, 4);// 打印恢复后的下三角矩阵,验证正确性for (int i = 0; i < 4; i++) {for (int j = 0; j < 4; j++) {printf("%d ", restoredLowerMatrix[i][j]);}printf("\n");}return 0;
}

(三)对角矩阵

  1. 存储特点
    • 对角矩阵是指除主对角线及其相邻若干条对角线上的元素外,其余元素均为 0 的矩阵。以三对角矩阵为例,其主对角线以及主对角线上下各一条对角线上有非零元素。
  2. 存储方式
    • 可以将三对角矩阵的非零元素按行优先存储到一维数组 da 中。对于三对角矩阵中的元素 a[i][j],当 |i - j| <= 1 时为非零元素。其在一维数组中的下标 k 计算如下:
      [k = 3i - 1 + j - i = 2i + j - 1](当 (i = 0) 时,(k = j))
  3. C 语言示例
// 存储三对角矩阵到一维数组
void storeTriDiagonalMatrix(int a[][100], int da[], int n) {int k = 0;for (int i = 0; i < n; i++) {for (int j = i - 1; j <= i + 1; j++) {if (j >= 0 && j < n) {da[k++] = a[i][j];}}}
}// 根据一维数组恢复三对角矩阵
void restoreTriDiagonalMatrix(int a[][100], int da[], int n) {int k = 0;for (int i = 0; i < n; i++) {for (int j = i - 1; j <= i + 1; j++) {if (j >= 0 && j < n) {a[i][j] = da[k++];} else {a[i][j] = 0;}}}
}int main() {// 声明一个 5 阶三对角矩阵并初始化int triDiagonalMatrix[5][5] = {{1, 2, 0, 0, 0},{3, 4, 5, 0, 0},{0, 6, 7, 8, 0},{0, 0, 9, 10, 11},{0, 0, 0, 12, 13}};int da[14];  // 用于存储三对角矩阵的一维数组// 存储三对角矩阵storeTriDiagonalMatrix(triDiagonalMatrix, da, 5);// 恢复三对角矩阵int restoredTriMatrix[5][5];restoreTriDiagonalMatrix(restoredTriMatrix, da, 5);// 打印恢复后的三对角矩阵,验证正确性for (int i = 0; i < 5; i++) {for (int j = 0; j < 5; j++) {printf("%d ", restoredTriMatrix[i][j]);}printf("\n");}return 0;
}

(四)稀疏矩阵

  1. 存储特点
    • 稀疏矩阵是指非零元素个数远小于矩阵元素总个数的矩阵。
  2. 存储方式 - 三元组顺序表
    • 可以使用三元组顺序表来存储稀疏矩阵。三元组顺序表包含三个一维数组,分别存储非零元素的行下标、列下标和值。
    • 首先定义三元组结构体:
typedef struct {int row;int col;int value;
} Triple;
  • 然后定义三元组顺序表结构体:
typedef struct {Triple data[100];int num;  // 非零元素个数
} SparseMatrix;
  • 存储稀疏矩阵到三元组顺序表的函数:
// 存储稀疏矩阵到三元组顺序表
void storeSparseMatrix(int a[][100], SparseMatrix *sm, int m, int n) {sm->num = 0;for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if (a[i][j]!= 0) {sm->data[sm->num].row = i;sm->data[sm->num].col = j;sm->data[sm->num].value = a[i][j];sm->num++;}}}
}
  • 根据三元组顺序表恢复稀疏矩阵的函数:
// 根据三元组顺序表恢复稀疏矩阵
void restoreSparseMatrix(int a[][100], SparseMatrix sm, int m, int n) {for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {a[i][j] = 0;}}for (int k = 0; k < sm.num; k++) {a[sm.data[k].row][sm.data[k].col] = sm.data[k].value;}
}
  • C 语言示例
int main() {// 声明一个稀疏矩阵并初始化int sparseMatrix[5][5] = {{0, 0, 3, 0, 0},{0, 0, 0, 0, 0},{0, 6, 0, 0, 0},{0, 0, 0, 0, 9},{0, 0, 0, 0, 0}};SparseMatrix sm;// 存储稀疏矩阵到三元组顺序表storeSparseMatrix(sparseMatrix, &sm, 5, 5);// 恢复稀疏矩阵int restoredSparseMatrix[5][5];restoreSparseMatrix(restoredSparseMatrix, sm, 5, 5);// 打印恢复后的稀疏矩阵,验证正确性for (int i = 0; i < 5; i++) {for (int j = 0; j < 5; j++) {printf("%d ", restoredSparseMatrix[i][j]);}printf("\n");}return 0;
}

通过对多维数组和各种特殊矩阵的存储与压缩方式的深入理解和掌握,能够在处理大规模数据矩阵相关的问题时,有效地减少存储空间的占用并提高数据处理的效率。在实际应用中,例如在图像处理、科学计算(如有限元分析中的矩阵运算)、数据挖掘等领域,这些技术都有着广泛的应用前景。
在图像处理中,图像可以看作是一个二维矩阵,当处理一些具有特定对称性或稀疏性的图像数据时,利用相应的矩阵存储和压缩技术,可以减少内存的占用,加快图像的处理速度,如对一些纹理具有对称性的图像进行压缩存储以便后续的传输或分析。
在科学计算里,很多物理问题的数学模型最终会转化为大规模的矩阵运算。例如在结构力学的有限元分析中,得到的刚度矩阵往往是对称矩阵或稀疏矩阵,采用合适的存储方式能够显著降低存储需求,提高计算效率,使得在有限的计算机资源下能够处理更复杂的结构模型。
在数据挖掘领域,一些关联矩阵或相似度矩阵可能具有稀疏性的特点,运用稀疏矩阵的存储和处理方法,可以高效地挖掘数据之间的潜在关系,发现有价值的信息模式,如在社交网络分析中处理用户之间的关联矩阵,挖掘用户群体的特征和行为模式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/61921.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

openssl颁发包含主题替代名的证书–SAN

原文地址&#xff1a;openssl颁发包含主题替代名的证书–SAN – 无敌牛 欢迎参观我的个人博客&#xff1a;无敌牛 – 技术/著作/典籍/分享等 在 X.509 证书中&#xff0c;commonName&#xff08;CN&#xff09;字段只能有一个值。如果让证书支持多个域名和IP地址&#xff0c;…

从尾到头打印链表 剑指offer

题目描述 输入一个链表的头节点&#xff0c;从尾到头反过来打印出每个节点的值。 链表节点定义如下&#xff1a; struct ListNode {int m_nKey;ListNode*m_pNext; }; 代码实现 栈实现&#xff1a; 递归实现&#xff1a; 但是用递归实现可能存在的问题&#xff1a;

ajax基础

一&#xff1a;express框架 在终端输入nodejs文件名 // 引入express const express require(express); //创建应用对象 const app express(); //创建路由规则 app.get(/,(request,response) > {//设置响应response.send(Hello Express); }); // 监听3000端口 app.lis…

免费实用在线AI工具集合 - 加菲工具

免费在线工具-加菲工具 https://orcc.online/ 在线录屏 https://orcc.online/recorder 时间戳转换 https://orcc.online/timestamp Base64 编码解码 https://orcc.online/base64 URL 编码解码 https://orcc.online/url Hash(MD5/SHA1/SHA256…) 计算 https://orcc.online/h…

UE5肉鸽游戏教程学习

学习地址推荐&#xff1a;UE5肉鸽项目实战教程_哔哩哔哩_bilibili

101页PDF | 德勤_XX集团信息化顶层规划设计信息化总体解决方案(限免下载)

一、前言 这份报告是一份关于集团信息化顶层规划设计的总体解决方案&#xff0c;旨在通过信息化转型提升集团管控和企业运营效率。报告回顾了项目的背景、目标和工作过程&#xff0c;分析了集团面临的内部和外部挑战&#xff0c;并提出了一系列解决方案&#xff0c;包括自上而…

L14.【LeetCode笔记】返回倒数第k个节点

目录 1.题目 2.分析 思路 代码 提交结果 1.题目 面试题 02.02. 返回倒数第 k 个节点 实现一种算法&#xff0c;找出单向链表中倒数第 k 个节点。返回该节点的值。 注意&#xff1a;本题相对原题稍作改动 示例&#xff1a; 输入&#xff1a; 1->2->3->4->5 和 …

【zookeeper03】消息队列与微服务之zookeeper集群部署

ZooKeeper 集群部署 1.ZooKeeper 集群介绍 ZooKeeper集群用于解决单点和单机性能及数据高可用等问题。 集群结构 Zookeeper集群基于Master/Slave的模型 处于主要地位负责处理写操作)的主机称为Leader节点&#xff0c;处于次要地位主要负责处理读操作的主机称为 follower 节点…

STM32端口模拟编码器输入

文章目录 前言一、正交编码器是什么&#xff1f;二、使用步骤2.1开启时钟2.2配置编码器引脚 TIM3 CH1(PA6) CH2 (PA7)上拉输入2.3.初始化编码器时基2.4 初始化编码器输入2.5 配置编码器接口2.6 开启定时器2.7获取编码器数据 三、参考程序四、测试结果4.1测试方法4.2串口输出结果…

【Mybatis】@Param注解 resultMap手动映射

文章目录 一、映射文件参数二、查询映射2-1 一对一2-2 一对多2-3 总结 一、映射文件参数 Param 注解官方文档解释 1、单个参数&#xff08;对象&#xff09;不使用注解 public int save(User user);<!-- 添加用户 --> <insert id"save" parameterType&quo…

正则表达式灾难:重新认识“KISS原则”的意义

RSS Feed 文章标题整理 微积分在生活中的应用与思维启发 捕鹿到瞬时速度的趣味探索 微积分是一扇通往更广阔世界的门&#xff0c;从生活中学习思维的工具。 数据库才是最强架构 你还在被“复杂架构”误导吗&#xff1f; 把业务逻辑写入数据库&#xff0c;重新定义简单与效率。…

C#基础上机练习题

21.计算500-800区间内素数的个数cn&#xff0c;并按所求素数的值从大到小的顺序排列&#xff0c;再计算其间隔加、减之和&#xff0c;即第1个素数-第2个素数第3个素数-第4个素数第5个素数……的值sum。请编写函数实现程序的要求&#xff0c;把结果cn和sum输出。 22.在三位整数…

【STM32】在 STM32 USB 设备库添加新的设备类

说实话&#xff0c;我非常想吐槽 STM32 的 USB device library&#xff0c;总感觉很混乱。 USB Device library architecture 根据架构图&#xff1a; Adding a custom class 如果你想添加新的设备类&#xff0c;必须修改的文件有 usbd_desc.cusbd_conf.cusb_device.c 需要…

多头数(head number);d_model、d_k;词嵌入维度之间的关系;多头是对不同维度的特征分开提取,意义在于将并行执行

目录 多头是对不同维度的特征分开提取,意义在于将并行执行 之后的每头提取的特征仅仅进行矩阵拼接 多头数(head number) d_model、d_k 词嵌入维度之间的关系 词嵌入的维度(d_model)决定了权重矩阵的形状 一、概念解释 二、关系举例说明 多头数,权重矩阵的长度和词…

Mac配置maven环境及在IDEA中配置Maven

Mac配置maven环境及在IDEA中配置Maven 1. 介绍 Maven是一款广泛用于Java等JVM语言项目的工具&#xff0c;它以项目对象模型&#xff08;POM&#xff09;为基础进行项目管理&#xff0c;通过POM文件来定义项目信息和依赖关系。同时&#xff0c;它也是构建自动化工具&#xff0…

Qt中2D绘制系统

目录 一、Qt绘制系统 1.1Qt绘制基本概念 1.2 绘制代码举例 1.3画家 1.3.1 QPainter的工作原理&#xff1a; 1.3.2 自定义绘制饼状图&#xff1a; 1.4画笔和画刷 1.4.1画笔 1.4.2 画刷填充样式 1.5 反走样和渐变 1.6绘制设备 1.7坐标变换 1.8QPainterPath 1.9绘制文…

运维Tips:Docker或K8s集群拉取Harbor私有容器镜像仓库配置指南

[ 知识是人生的灯塔,只有不断学习,才能照亮前行的道路 ] Docker与Kubernetes集群拉取Harbor私有容器镜像仓库配置 描述:在现在微服务、云原生的环境下,通常我们会在企业中部署Docker和Kubernetes集群,并且会在企业内部搭建Harbor私有镜像仓库以保证开发源码安全,以及加快…

2022年计算机网络408考研真题解析

第一题&#xff1a; 解析&#xff1a;网络体系结构-数据链路层 在ISO网络参考模型中&#xff0c;运输层&#xff0c;网络层和数据链路层都实现了流量的控制功能&#xff0c;其中运输层实现的是端到端的流量控制&#xff0c;网络层实现的是整个网络的流量控制&#xff0c;数据链…

鸿蒙NEXT开发案例:文字转拼音

【引言】 在鸿蒙NEXT开发中&#xff0c;文字转拼音是一个常见的需求&#xff0c;本文将介绍如何利用鸿蒙系统和pinyin-pro库实现文字转拼音的功能。 【环境准备】 • 操作系统&#xff1a;Windows 10 • 开发工具&#xff1a;DevEco Studio NEXT Beta1 Build Version: 5.0.…

使用sk-learn 理解TF-IDF

TF-IDF&#xff08;Term Frequency-Inverse Document Frequency&#xff09;是一种常用的文本挖掘技术&#xff0c;用于评估一个词语在一组文档中的重要性。它广泛应用于信息检索和文本挖掘中&#xff0c;尤其是在搜索引擎和推荐系统中。 组成部分 TF-IDF 由两个部分组成&…