[数据结构] 数组与特殊矩阵

这篇具有很好参考价值的文章主要介绍了[数据结构] 数组与特殊矩阵。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

写在前面

偷懒,先写了数组,队列要画图,所以今天就先不写了

数组的定义

数组是由n个相同类型的数据元素构成的有限序列。每个数据元素被称为一个数组元素,每个元素在n个线性关系中的序号称为该元素的下标,下标的取值范围称为数组的维界

数组与线性表的关系:数组是线性表的推广。一维数组可视为一个线性表,二维数组可视为其元素是定长数组的线性表。因此,除结构的初始化和销毁外,数组只会有存取元素和修改元素的操作。

数组的顺序存储

一维数组

\(A[0 \dots n-1]\)为例,其存储结构关系式为:

\[LOC(a_i) = LOC(a_0) + i \times L(0 \leq i < n) \]

其中,\(L\)是每个数组元素所占的存储单元。

多维数组

以二维数组为例。设二维数组的行下标与列下标的范围分别为\([0, h_1]\)\([0,h_2]\)

按行优先

先行后列,先存储行号较小的元素,行号相等先存储列号较小的元素。存储结构关系式为:

\[LOC(a_{i,j}) = LOC(a_{0,0})+[i \times(h_2+1) + j] \times L \]

例如对于数组\(A_{[2][3]}\)。它按行优先方式在内存中的存储形式如下所示:

\[\left[ \begin{matrix} a_{[0][0]} & a_{[0][1]} & a_{[0][2]} \\ a_{[1][0]} & a_{[1][1]} & a_{[1][2]} \\ \end{matrix} \right] \]
\(a_{[0][0]}\) \(a_{[0][1]}\) \(a_{[0][2]}\) \(a_{[1][0]}\) \(a_{[1][1]}\) \(a_{[1][2]}\)

列优先

存储结构关系式为:

\[LOC(a_{i,j}) = LOC(a_{0,0})+[j \times (h_1 + 1) + i] \times L \]

例如对于数组\(A_{[2][3]}\)。它按行优先方式在内存中的存储形式如下所示:

\[\left[ \begin{matrix} a_{[0][0]} & a_{[0][1]} & a_{[0][2]} \\ a_{[1][0]} & a_{[1][1]} & a_{[1][2]} \\ \end{matrix} \right] \]
\(a_{[0][0]}\) \(a_{[1][0]}\) \(a_{[0][1]}\) \(a_{[1][1]}\) \(a_{[0][2]}\) \(a_{[1][2]}\)

特殊矩阵的压缩存储

压缩存储:指为多个值相同的元素只分配一个存储空间,对零元素不分配空间;

特殊矩阵:指具有许多相同矩阵元素或零元素,并且这些相同矩阵元素或零元素的分布具有一定规律性的矩阵;

特殊矩阵的压缩存储:找出特殊矩阵中值相同的矩阵元素的分布规律,把那些呈现规律性分布的、值相同的多个矩阵元素压缩存储到一个存储空间中。

对称矩阵

对一个n阶矩阵\(A\)中的任意一个元素\(a_{i,j}\)都有\(a_{i, j} = a_{j, i}(1 \leq i, j \leq n)\),则称其为对称矩阵

\[\left[ \begin{matrix} a_{1,1} & a_{1,2} & \cdots & a_{1,n} \\ a_{2,1} & a_{2,2} & \cdots & a_{2,n} \\ \vdots & \vdots & \ddots & \vdots \\ a_{n,1} & a_{n,2} & \cdots & a_{n,n} \end{matrix} \right] \]

很显然,对于n阶对称矩阵,上三角区所有元素和下三角区的对应元素相同,采用二维数组存放,会造成大范围的空间浪费,因此我们把其存放在一维数组\(B[\frac{n(n+1)}{2}]\)中。

比如只存放下三角部分的元素:

在数组\(B\)中,位于元素\(a_{i, j}\)前的元素个数为:

第1行:1个(\(a_{1,1}\)

第2行:2个(\(a_{2,1},a_{2,2}\)

\(\dots\)

\(i-1\)行:\(i-1\)个(\(a_{i-1,1},a_{i-1,2} \dots ,a_{i-1,i-1}\)

\(i\)行:\(j-1\)个(\(a_{i,1},a_{i,2}, \dots , a_{i,j-1}\)

因此,元素\(a_{i,j}\)在数组\(B\)中的下标\(k = 1 + 2 + \dots + (i - 1) + j - 1 = \frac{i(i - 1)}{2} + j - 1\)

因此,元素下标之间对应关系如下:

\[k = \begin{cases} \frac{i(i-1)}{2} + j - 1&, \qquad i \geq j \\ \frac{j(j-1)}{2} + i - 1&, \qquad i < j \end{cases} \]

三角矩阵

下三角矩阵

\[\left[ \begin{matrix} a_{1,1} \\ a_{2,1} & a_{2,2} \\ \vdots & \vdots & \ddots \\ a_{n,1} & a_{n,2} & \cdots a_{n,n} \end{matrix} \right] \]

上三角区为统一常量。元素下标之间的对应关系为:

\[k = \begin{cases} \frac{i(i-1)}{2} + j - 1 &, \qquad i \geq j \\ \frac{n(n-1)}{2} &, \qquad i < j \end{cases} \]
下标 0 1 2 3 4 5 \(\cdots\) \(\frac{n(n+1)}{2}\)
元素 \(a_{1,1}\) \(a_{2,1}\) \(a_{2,2}\) \(a_{3,1}\) \(a_{3,2}\) \(a_{3,3}\) \(\cdots\) \(a_{n,1}\) \(a_{n,2}\) \(\cdots\) \(a_{n,n}\) \(c\)
行号 第一行 第二行 第二行 第三行 第三行 第三行 \(\cdots\) 第n行 第n行 \(\cdots\) 第n行 常数项

上三角矩阵

\[\left[ \begin{matrix} a_{1,1} & a_{1,2} & \cdots & a_{1,n} \\ & a_{2,2} & \cdots & a_{2,n} \\ & & \ddots & \vdots \\ & & & a_{n,n} \end{matrix} \right] \]

与上文类似地,位于元素\(a_{i,j}(i \leq j)\)前面的元素个数为:

第1行:\(n\)

第2行:\(n-1\)

\(\dots\)

\(i-1\)行:\(n - i + 2\)

\(i\)行:\(j-1\)

因此,元素\(a_{i,j}\)在数组\(B\)中的下标\(k = n + (n - 1) + \dots + (n - i + 2) + (j - i + 1) - 1\)

因此,元素下标之间对应关系如下:

\[k = \begin{cases} \frac{(i-1)(2n - i + 2)}{2} + j - i &, \qquad i \leq j \\ \frac{n(n+1)}{2} &, \qquad i > j \end{cases} \]
下标 0 1 \(\cdots\) \(\frac{n(n+1)}{2}\)
元素 \(a_{1,1}\) \(a_{1,2}\) \(\cdots\) \(a_{1,n}\) \(a_{2,2}\) \(a_{2,3}\) \(\cdots\) \(a_{2,n}\) \(\cdots\) \(a_{n,n}\) \(c\)
行号 第一行 第一行 第一行 第一行 第二行 第二行 第二行 第二行 \(\cdots\) 第n行 常数

三对角矩阵

对n阶矩阵\(A\)中的任意元素\(a_{i,j}\),都有当\(|i-j| >1\)时,\(a_{i,j} = 0\)

\[\left[ \begin{matrix} a_{1,1} & a_{1,2} \\ a_{2,1} & a_{2,2} & a_{2,3} & & 0 \\ & a_{3,2} & a_{3,3} & a_{3,4} \\ & & \ddots & \ddots & \ddots \\ & 0 & & a_{n-1,n-2} & a_{n-1,n-1} & a_{n-1,n} \\ & & & & a_{n,n-1} & a_{n, n} \end{matrix} \right] \]

稀疏矩阵

矩阵中非零元素的个数t,相对于矩阵元素的个数s来说非常少,即\(s >> t\)的矩阵称为稀疏矩阵

我们可以用对应的三元组线性表来存储稀疏矩阵,如下例:

\[M = \left[ \begin{matrix} 4 & 0 & 0 & 0 \\ 0 & 0 & 6 & 0 \\ 0 & 9 & 0 & 0 \\ 0 & 23 &0 & 0 \end{matrix} \right] \]

对应的三元组为:

\[\left( \begin{matrix} i & j & a_{i,j} \\ 0 & 0 & 4 \\ 1 & 2 & 6 \\ 2 & 1 & 9 \\ 3 & 1 & 23 \end{matrix} \right) \]

下面,上代码,可以实现稀疏矩阵的输入、输出,稀疏矩阵对应三元组的加法、乘法、转置:文章来源地址https://www.toymoban.com/news/detail-825340.html

#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 10000

typedef int ElemType;

typedef struct {

    int i, j;
    ElemType e;

}Triple;


typedef struct {

    Triple data[MAXSIZE + 1];
    int mu, nu, tu;          //矩阵行数,列数和非0元个数

}TSMatrix;



//输入稀疏矩阵数据
void InPutM(TSMatrix& M) {
    printf("输入稀疏矩阵的 行数, 列数, 非0元个数 :\n");
    scanf_s("%d %d %d", &M.nu, &M.mu, &M.tu);
    printf("输入矩阵非0元素的 所在行i, 所在列j, 值e:\n");
    for (int k = 1; k <= M.tu; k++) {
        scanf_s("%d %d %d", &M.data[k].i, &M.data[k].j, &M.data[k].e);
    }
}



//打印稀疏矩阵三元组数据
void PrintM(TSMatrix T) {
    printf("  %d    %d    %d\n", T.mu, T.nu, T.tu);
    printf("  ------------\n");
    for (int k = 1; k <= T.tu; k++) {
        printf("  %d    %d    %d\n", T.data[k].i, T.data[k].j, T.data[k].e);
    }
}



//稀疏矩阵三元组加法
void AddSMatrix(TSMatrix a, TSMatrix b, TSMatrix& c) {
    int i = 0, j = 0, k = 0;
    ElemType v;                            //用于计算和
    if (a.mu != b.mu || a.nu != b.nu)       //两矩阵无法相加
        return;

    c.mu = a.mu;
    c.nu = a.nu;
    while (i < a.tu || j < b.tu)
    {
        //若行相等,看列
        if (a.data[i + 1].i == b.data[j + 1].i)
        {
            //行相同时的第一种情况
            if (a.data[i + 1].j < b.data[j + 1].j)
            {
                c.data[k + 1].i = a.data[i + 1].i;
                c.data[k + 1].j = a.data[i + 1].j;
                c.data[k + 1].e = a.data[i + 1].e;
                k++;
                i++;        //前往下一个a中的非0元
            }
            //行相同时的第二种情况
            else if (a.data[i + 1].j > b.data[j + 1].j)
            {
                c.data[k + 1].i = b.data[j + 1].i;
                c.data[k + 1].j = b.data[j + 1].j;
                c.data[k + 1].e = b.data[j + 1].e;
                k++;
                j++;        //前往下一个b中的非0元
            }
            //行相同的第三种情况
            else
            {
                v = a.data[i + 1].e + b.data[j + 1].e;
                if (v != 0)
                {
                    c.data[k + 1].i = a.data[i + 1].i;
                    c.data[k + 1].j = a.data[i + 1].j;
                    c.data[k + 1].e = v;
                    k++;
                }
                i++;
                j++;
            }
        }
        //若行不相同 的两种情况
        else if (i == a.tu || a.data[i + 1].i > b.data[j + 1].i && j != b.tu)
        {
            c.data[k + 1].i = b.data[j + 1].i;
            c.data[k + 1].j = b.data[j + 1].j;
            c.data[k + 1].e = b.data[j + 1].e;
            k++;
            j++;      //前往下一个b的非0元
        }
        else if (j == b.tu || a.data[i + 1].i < b.data[j + 1].i && i != a.tu)
        {
            c.data[k + 1].i = a.data[i + 1].i;
            c.data[k + 1].j = a.data[i + 1].j;
            c.data[k + 1].e = a.data[i + 1].e;
            k++;
            i++;      //前往下一个a的非0元
        }
    }
    c.tu = k;
}



//乘法辅助函数
int Getval(TSMatrix a, int i, int j) {
    int k = 1;
    while (k <= a.tu && (a.data[k].i != i || a.data[k].j != j))
        k++;
    if (k <= a.tu)
        return a.data[k].e;
    else
        return 0;
}



//稀疏矩阵三元组乘法
void MultSMatrix(TSMatrix a, TSMatrix b, TSMatrix& c) {
    int p = 0;
    ElemType s;
    if (a.nu != b.mu)
        return;

    for (int i = 1; i <= a.mu; i++) {
        for (int j = 1; j <= b.nu; j++) {
            s = 0;
            for (int k = 1; k <= a.nu; k++)
                s += Getval(a, i, k) * Getval(b, k, j);
            if (s != 0) {
                c.data[p + 1].i = i;
                c.data[p + 1].j = j;
                c.data[p + 1].e = s;
                p++;
            }
        }
    }
    c.mu = a.mu;
    c.nu = b.nu;
    c.tu = p;
}



//稀疏矩阵转置   (适用于 tu << mu × nu 的情况)
void TransposeSMatrix(TSMatrix M, TSMatrix& T) {
    T.mu = M.nu;                           //T行数等于原矩阵列数
    T.nu = M.mu;                           //T列数等于原矩阵行数
    T.tu = M.tu;
    if (!T.tu)
        return;

    int q = 1;                             //从列数小的开始,一一对应赋值
    for (int col = 1; col <= M.nu; ++col) {
        for (int 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++;
            }
        }
    }
}



//稀疏矩阵的快速转置算法
int cpot[MAXSIZE + 1], num[MAXSIZE + 1];   //辅助数组  
//cpot[col] 表示M中第col列第一个非0元在T.data中的位置
//num[col]  表示M中第col列中非0元的个数
void FastTransposeSMatrix(TSMatrix M, TSMatrix& T) {
    T.mu = M.nu;
    T.nu = M.mu;
    T.tu = M.tu;
    if (!T.tu)
        return;

    for (int col = 1; col <= M.mu; col++)
        num[col] = 0;                      //初始化为0

    for (int k = 1; k <= M.tu; k++)
        num[M.data[k].j]++;                //记录M.data[k].j列中非0元个数 (简易哈希表)

    cpot[1] = 1;                           //初始化第一个非0元的序号
    for (int col = 2; col <= M.mu; col++)   //求第col列中第一个非零元在T.data中的序号   
        cpot[col] = cpot[col - 1] + num[col - 1];

    for (int p = 1; p <= M.tu; p++) {
        int col = M.data[p].j;             //此时M对应三元组中的非0元的所在列
        int q = cpot[col];                  //q为当前非0元的应当放置的序号位置
        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]++;                       //cpot[col]++,对应下一个此列中非0元的序号
        //cpot[col]最后一直加到等于cpot[col + 1],第col列也就不会有更多的非0元了
    }
}




int main() {
    TSMatrix A, B, C, D;
    printf("输入稀疏矩阵A的三元组:\n");
    InPutM(A);
    PrintM(A);
    printf("\n输入稀疏矩阵B的三元组:\n");
    InPutM(B);
    PrintM(B);
    //printf("\n矩阵A与B相加得到矩阵C:\n");
    //AddSMatrix(A, B, C);
    //PrintM(C);
    printf("\n矩阵A与B相乘得到矩阵D:\n");
    MultSMatrix(A, B, D);
    PrintM(D);
    printf("\n");
    system("pause");
    system("cls");



    TSMatrix M, T, FT;
    printf("————稀疏矩阵转置测试————\n\n");
    InPutM(M);
    printf("\n稀疏矩阵转置前三元组: \n");
    PrintM(M);

    printf("\n稀疏矩阵转置结果: \n");
    TransposeSMatrix(M, T);
    PrintM(T);

    printf("\n稀疏矩阵的快速转置结果: \n");
    FastTransposeSMatrix(M, FT);
    PrintM(FT);
}

到了这里,关于[数据结构] 数组与特殊矩阵的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【数据结构】数组(稀疏矩阵、特殊矩阵压缩、矩阵存储、稀疏矩阵的快速转置、十字链表)

    前几期期链接: 【数据结构】栈与队列的概念和基本操作代码实现 【数据结构】树与二叉树的概念与基本操作代码实现 k维数组的定义: k 维数组 D = { a j 1 , j 2 , . . . , j k } k维数组D={ a_{j_1, j_2, ..., j_k} } k 维数组 D = { a j 1 ​ , j 2 ​ , ... , j k ​ ​ } k 0 称为数组的维数,

    2024年04月09日
    浏览(139)
  • 【数据结构】数组和字符串(四):特殊矩阵的压缩存储:稀疏矩阵——三元组表

    【数据结构】数组和字符串(一):矩阵的数组表示   矩阵是以按行优先次序将所有矩阵元素存放在一个一维数组中。但是对于特殊矩阵,如对称矩阵、三角矩阵、对角矩阵和稀疏矩阵等, 如果用这种方式存储,会出现大量存储空间存放重复信息或零元素的情况,这样会造

    2024年02月05日
    浏览(42)
  • 【数据结构】数组和字符串(五):特殊矩阵的压缩存储:稀疏矩阵——压缩稀疏行(CSR)

    【数据结构】数组和字符串(一):矩阵的数组表示   矩阵是以按行优先次序将所有矩阵元素存放在一个一维数组中。但是对于特殊矩阵,如对称矩阵、三角矩阵、对角矩阵和稀疏矩阵等, 如果用这种方式存储,会出现大量存储空间存放重复信息或零元素的情况,这样会造

    2024年02月05日
    浏览(51)
  • 【数据结构】特殊矩阵的压缩存储

    🌈 自在飞花轻似梦,无边丝雨细如愁 🌈   🌟 正式开始学习数据结构啦~此专栏作为学习过程中的记录 🌟 数组是由n个相同类型的数据元素所构成的有限序列 数组和线性表的关系: 数组是线性表的推广:一维数组可以看做是一个线性表,而对于二维数组而言,可以看成是有

    2024年02月11日
    浏览(44)
  • 数据结构--特殊矩阵的压缩存储

    各数组元素大小相同,且物理上连续存放。 数组元素a[i]的存放地址= LOC + i * sizeof(ElemType) ( 0 ≤ i 10 ) (0le i 10) ( 0 ≤ i 10 ) 注:除非题目特别说明,否则数组 下标默认从 0 开始 color{red}下标默认从0开始 下标默认从 0 开始 注意审题 ! 易错 ! color{purple}注意审题!易错! 注意审题

    2024年02月16日
    浏览(58)
  • 数据结构(五)----特殊矩阵的压缩存储

    目录 1.一维数组的存储结构 2.二维数组的存储结构 3.普通矩阵的存储 4.特殊矩阵的压缩存储 (1)对称矩阵 (2)三角矩阵 (3)三对角矩阵 (4)稀疏矩阵的压缩存储 1.一维数组的存储结构 一维数组的定义如下: ElemType a[10]; 各数组元素大小相同,且物理上连续存放。 数组元

    2024年04月28日
    浏览(37)
  • 【考研】数据结构——特殊矩阵的压缩存储(含真题)

    本文内容源于对《数据结构(C语言版)》(第2版)、王道讲解学习所得心得、笔记整理和总结。 本文主要以举例子的方式讲解考研选择题型中的特殊矩阵的压缩存储知识点,配以图文(含408真题)。 可搭配以下链接进行学习: 【2023考研】数据结构常考应用典型例题(含真

    2024年02月03日
    浏览(52)
  • 【数据结构】特殊矩阵的压缩存储(对称矩阵,三角矩阵和三对角矩阵)

    目录 1.对阵矩阵 2.三角矩阵 3.三对角矩阵(带状矩阵) 定义:若对一个n阶矩阵A中的任意一个元素 aᵢ,ⱼ 都有aᵢ,ⱼ=aⱼ,ᵢ (1≤i,j≤n),则称其为对称矩阵。 存储策略:只存储主对角线+下三角区(或主对角线+上三角区),以主对角线+下三角区为例,按照行优先把这些元

    2024年01月16日
    浏览(41)
  • 【数据结构】特殊矩阵的压缩存储|保姆级详解+图解

    作者: 努力学习的大一在校计算机专业学生,热爱学习和创作。目前在学习和分享:算法、数据结构、Java等相关知识。 博主主页: @是瑶瑶子啦 所属专栏: 【数据结构】:该专栏专注于数据结构知识,持续更新,每一篇内容优质,浅显易懂,不失深度! 近期目标: 写好专栏

    2024年02月02日
    浏览(35)
  • 数据结构-拓展突破-特殊矩阵(对称矩阵,三角矩阵,三对角矩阵,稀疏矩阵)的压缩存储)

    对称矩阵的定义: 若n阶方阵中任意一个元素a,都有a(i,j)=a(j,i)则该矩阵为对称矩阵 也就是说对称矩阵的元素关于对角线对称。对角线上半部分称为上三角区,下半部分称为下三角区。 对称矩阵的压缩存储策略:只存储主对角线+下三角区(或主对角线+上三角区) 可以定义一维数

    2023年04月08日
    浏览(61)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包