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

news2024/11/26 23:19:22

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

一、多维数组的存储

(一)基本概念

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

(二)行优先存储

以二维数组为例,行优先存储是先存储第一行的元素,然后再存储第二行的元素,依此类推。对于一个 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.coloradmin.cn/o/2248086.html

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

相关文章

【案例学习】如何使用Minitab实现包装过程的自动化和改进

Masimo 是一家全球性的医疗技术公司&#xff0c;致力于开发和生产各种行业领先的监控技术&#xff0c;包括创新的测量、传感器和患者监护仪。在 Masimo Hospital Automation 平台的助力下&#xff0c;Masimo 的连接、自动化、远程医疗和远程监控解决方案正在改善医院内外的护理…

Git旧文件覆盖引发思考

一天&#xff0c;我的同事过来找到我&#xff0c;和我讲&#xff1a;张叫兽&#xff0c;大事不好&#xff0c;我的文件被人覆盖了。git是真的不好用啊 git不好用&#xff1f;文件被覆盖&#xff1b;瞬间我似乎知道了什么&#xff0c;让我想到了某位男明星的语法&#xff1a;他…

CSP/信奥赛C++语法基础刷题训练(23):洛谷P1217:[USACO1.5] 回文质数 Prime Palindromes

CSP/信奥赛C语法基础刷题训练&#xff08;23&#xff09;&#xff1a;洛谷P1217&#xff1a;[USACO1.5] 回文质数 Prime Palindromes 题目描述 因为 151 151 151 既是一个质数又是一个回文数&#xff08;从左到右和从右到左是看一样的&#xff09;&#xff0c;所以 151 151 …

嵌入式系统与OpenCV

目录 一、OpenCV 简介 二、嵌入式 OpenCV 的安装方法 1. Ubuntu 系统下的安装 2. 嵌入式 ARM 系统中的安装 3. Windows10 和树莓派系统下的安装 三、嵌入式 OpenCV 的性能优化 1. 介绍嵌入式平台上对 OpenCV 进行优化的必要性。 2. 利用嵌入式开发工具&#xff0c;如优…

SAP BC 记录一次因为HANA服务器内存满的问题

用户操作 DB02 进入hana数据库服务器 free -g 内存用完了 如下图 解决方案&#xff1a;增加内存 操作 关应用服务->关闭数据库服务->关闭hana服务器->加内存->起hana服务器->起hana服务->启动应用服务。

ArcGIS应用指南:ArcGIS制作局部放大地图

在地理信息系统&#xff08;GIS&#xff09;中&#xff0c;制作详细且美观的地图是一项重要的技能。地图制作不仅仅是简单地将地理数据可视化&#xff0c;还需要考虑地图的可读性和美观性。局部放大图是一种常见的地图设计技巧&#xff0c;用于展示特定区域的详细信息&#xff…

python画图|无坐标轴自由划线操作fig.add_artist(lines.Line2D()函数

【1】引言 新发现了一种自由划线操作函数&#xff0c;和大家共享。 【2】官网教程 点击下述代码&#xff0c;直达官网&#xff1a; https://matplotlib.org/stable/gallery/misc/fig_x.html#sphx-glr-gallery-misc-fig-x-py 官网代码非常简洁&#xff0c;我进行了解读。 …

深度解析:Nginx模块架构与工作机制的奥秘

文章目录 前言Nginx是什么?Ngnix特点&#xff1a; 一、Nginx模块与工作原理1.Nginx的模块1.1 Nginx模块常规的HTTP请求和响应的流程图:1.2 Nginx的模块从结构上分为如下三类&#xff1a;1.3 Nginx的模块从功能上分为如下三类: 2.Nginx的进程模型2.1 Nginx进程结构2.2 nginx进程…

抖音SEO矩阵系统:开发技术分享

市场环境剖析 短视频SEO矩阵系统是一种策略&#xff0c;旨在通过不同平台上的多个账号建立联系&#xff0c;整合同一品牌下的各平台粉丝流量。该系统通过遵循每个平台的规则和内容要求&#xff0c;输出企业和品牌形象&#xff0c;以矩阵形式增强粉丝基础并提升商业价值。抖音作…

面试经典 150 题:205,55

205. 同构字符串 【解题思路】 来自大佬Krahets 【参考代码】 class Solution { public:bool isIsomorphic(string s, string t) {map<char, char> Smap, Tmap;for(int i0; i<s.size(); i){char a s[i], b t[i];//map容器存在该字符&#xff0c;且不等于之前映射…

STM32 Keil5 attribute 关键字的用法

这篇文章记录一下STM32中attribute的用法。之前做项目的时候产品需要支持远程升级&#xff0c;要求版本只能向上迭代&#xff0c;不支持回退。当时想到的方案是把版本号放到bin文件的头部&#xff0c;设备端收到bin文件的首包部数据后判断是否满足升级要求&#xff0c;这里就可…

【Redis 缓存策略】更新、穿透、雪崩、击穿、布隆过滤

目录 缓存简单介绍 缓存更新策略 缓存更新需求 数据库缓存不一致解决方案 先操作缓存还是先操作数据库&#xff1f; 先删除缓存&#xff0c;再操作数据库 先操作数据库&#xff0c;再删除缓存 总结 删除缓存还是更新缓存&#xff1f; 保证缓存与数据库的操作的同时成功或失败 …

利用c语言详细介绍下栈的实现

数据结构中&#xff0c;栈是一种线性结构&#xff0c;数据元素遵循后进先出的原则。栈的一端为栈顶&#xff0c;一端为栈底或栈尾&#xff0c;数据只在栈顶端进行操作。新插入数据称为入栈或者压栈&#xff0c;删除数据叫做出栈或者退栈。 一、图文介绍 我们通过建立一个stack…

5.5 W5500 TCP服务端与客户端

文章目录 1、TCP介绍2、W5500简介2.1 关键函数socketlistensendgetSn_RX_RSRrecv自动心跳包检测getSn_SR 1、TCP介绍 TCP 服务端&#xff1a; 创建套接字[socket]&#xff1a;服务器首先创建一个套接字&#xff0c;这是网络通信的端点。绑定套接字[bind]&#xff1a;服务器将…

Transformer详解及衍生模型GPT|T5|LLaMa

简介 Transformer 是一种革命性的神经网络架构&#xff0c;首次出现在2017年的论文《Attention Is All You Need》中&#xff0c;由Google的研究团队提出。与传统的RNN和LSTM模型不同&#xff0c;Transformer完全依赖于自注意力&#xff08;Self-Attention&#xff09;机制来捕…

计算机网络基础全攻略:探秘网络构建块(1/10)

一、计算机网络基础概念 计算机网络是指将地理位置不同的具有独立功能的多台计算机及其外部设备&#xff0c;通过通信线路和通信设备连接起来&#xff0c;在网络操作系统&#xff0c;网络管理软件及网络通信协议的管理和协调下&#xff0c;实现资源共享和信息传递的计算机系统…

Android 应用测试的各种环境问题记录(Instrumentation测试)

报错记录 failed to configure packages targetSdkVersion&#xff08;未解决&#xff09; failed to configure com.demo.test.SettingsActivityTest.testOnCreate_withNullSavedInstanceState: Package targetSdkVersion34 > maxSdkVersion32 java.lang.IllegalArgumentE…

Python 爬虫从入门到(不)入狱学习笔记

爬虫的流程&#xff1a;从入门到入狱 1 获取网页内容1.1 发送 HTTP 请求1.2 Python 的 Requests 库1.2 实战&#xff1a;豆瓣电影 scrape_douban.py 2 解析网页内容2.1 HTML 网页结构2.2 Python 的 Beautiful Soup 库 3 存储或分析数据&#xff08;略&#xff09; 一般爬虫的基…

周志华深度森林deep forest(deep-forest)最新可安装教程,仅需在pycharm中完成,超简单安装教程

1、打开pycharm 没有pycharm的&#xff0c;在站内搜索安装教程即可。 2、点击“文件”“新建项目” 3、创建项目&#xff0c;Python版本中选择Python39。如果没有该版本&#xff0c;选择下面的Python 3.9下载并安装。 4、打开软件包&#xff0c;搜索“deep-forest”软件包&am…

用python将一个扫描pdf文件改成二值图片组成的pdf文件

使用墨水屏读书现在似乎越来越流行&#xff0c;这确实有一定的好处&#xff0c;例如基本不发热&#xff0c;电池续航时间超长&#xff0c;基本不能游戏所以有利于沉浸式阅读&#xff0c;还有不知道是不是真的有用的所谓防蓝光伤害。但是&#xff0c;如果阅读的书籍是扫描图片组…