数据结构复习之多维数组与矩阵

一种比特殊的数据结构。

知识点

多维数组和运算

定义

1、一维数组
是一种元素个数固定的线性表。

2、多维数组
是一种复杂的数据结构,可以看成是线性表的推广,一个n维数组可视为其数据元素为n-1维数组的线性表。

顺序存储

二维数组可有两种存储方法:一种是以行序为主序的存储方式,另一种是以列序为主序的存储方式。在C语言中,采用以行为主序存储。一般二维数组不采取链式存储

二维存储位置计算

对于C语言的二维数组A[m][n],下标从0开始,假设一个数组元素占d个存储单元,则二维数组中任一元素a[i][j]的存储位置可由下式确定:求这个元素之前存了多少元素

loc(A[i][j])=loc(A[0][0])+(i *n + j) * d
会推导,明白思想,不要记。

三维数组存储位置

三维数组A[m][n][p],下标从0开始,假设一个数组元素占d个存储单元,则三维数组中任一元素a[i][j][k]的存储位置可由下式确定:

loc(A[i][j][k])=loc(A[0][0][0]+(i *n *p+ j*p+k) * d

数组转换置算法实现

对于一个m×n的矩阵A,其转置矩阵是一个n×m的矩阵B,而且B[i][j]=A[j][i],0≤i≤n-1,0≤j≤m-1。假设m=5,,n=8。

void trsmat(int a[][8], int b[][5], int m, int n)
{
    int i, j;
    for (j = O; j < m; j++)
        for (i = 0; i < n; i++)
            b[i][j] = a[j][i];
}

另一种方法:
一维数组实现

矩阵的压缩存储

特殊矩阵:
是相同值的元素或者零元素在矩阵中的分布有一定规律的矩阵。

对称矩阵

若n阶方阵A中的元素满足下述性质:

aij=aji (0≤i,j≤n-1)

则称A为n阶的对称矩阵。

对于一个n阶对称矩阵,可只存储其下三角矩阵:如下图所示:在这里插入图片描述

以行序为主序存储其下三角(包括对角线)中的元素,将元素压缩存储到1+2+3+…+n=n(n+1)/2个元素的存储空间中,数组M[k]和aij的对应关系:如下图:在这里插入图片描述

三角矩阵

在这里插入图片描述

主对角线上/下方均为常数c或零
三角矩阵可压缩存储到数组M[n(n+1)/2+1]中。
下三角矩阵中,以行序为主序存放,与对称矩阵类是,M[k]和aij的对应关系是:
在这里插入图片描述

上三角矩阵中,主对角线上的第i行有n-i+1个元素,以行序为主序存放,M[k]和aij的对应关系是:
在这里插入图片描述

稀疏矩阵

含有大量的零元素且零元素分布没有规律矩阵称为稀疏矩阵。

三元组表来存储稀疏

每个三元组元素对应稀疏矩阵中的一个非零元素,包含有该元素的行号、列号和元素值。每个三元组元素在线性表中是按照行号值的升序为主序、列号值的升序为辅序(即行号值相同再按列号值顺序)排列的。
三元组数据结构定义:

#define Maxsize 1000 //假设非零元素个数的最大为1000个

typedef struct {
    int i,j; //非零元素的行号、列号(下标)
    DataType v; //非零元素值
} TriTupleNode;

typedef struct {
    TriTupleNode data[Maxsize];//存储三元组的数组
    int m,n,t; //矩阵的行数、列数和非零元素个数
} TSMatrix; //稀疏矩阵类型

实例

实现以三元组表结构存储的稀疏矩阵的转置运算。所谓的转置就是行与列互换。
在这里插入图片描述

一般转置算法

对M中的每一列col(0≤col≤a.n-1)从头至尾依次扫描三元组表,找出所有列号等col的那些三元组,并将它们的行号和列号互换后再依次存入b->data中,这样就可得到T的按行优先的三元组表。

void TransMatrix(TSMatrix a, TSMatrix *b)
{
    //a和*b是矩阵M、T的三元组表表示,求稀疏矩阵M的转置T
    int p, q, col;
    b->m = a.n;
    b->n = a.m; //M和T行列数互换
    b->t = a.t; //赋值非零元素个数
    if (b->t <= 0)
        printf("M中无非零元素!");
    else {
        q = 0;
        for (col = 0; col < a.n; ++col)
            for (p = 0; p < a.t; ++p) //扫描M的三元组表
                if (a.data[p].j == col) { //找与col相等的三元组
                    b->data[q].i = a.data[p].j;
                    b->data[q].j = a.data[p].i;
                    b->data[q].v = a.data[p].v;
                    ++q;
                }
    }
}

该算法仅适用于非零元素个数t远远小于矩阵元素个数m×n的情况。因为算法的时间复杂度为O(n×t),即与稀疏矩阵M的列数和非零元素个数的乘积成正比,相对来说是比较大的

快速转置算法

创建两个数组num和rownext。num[j]存放矩阵第j列上非零元素个数,rownext[i]代表转置矩阵第i行的下一个非零元素在b中的位置。

void FaStTran(TSMatfix a, TSMatrix *b)
{
    int col, p, t, q;

    int *num, *rownext;
    num = (int *)calloc(a.n + 1, 4); // 分配n+1个长度为4的连续空间
    rownext = (int *)calloc(a.m + 1, 4); // 分配m+1个长度为4的连续空间
    b->m = a.n;
    b->n = a.m;
    b->t = a.t;
    if (b->t) {
        for (col = 0; col < a.n; ++col)
            num[col] = 0; //初始化
        for (t = 0; t < a.t; ++t)
            ++num[a.data[t].j]; //计算每列非零元素数
        rownext[0] = 0;
        for (col = 1; col < a.n; ++col) //给出b中每一行的起始点
            rownext[col] = rownext[col - 1] + num[col - 1];
        for (p = 0; p < a.t; ++p) { //执行转置操作
            col = a.data[p].j;
            q = rownext[col];
            b->data[q].i = a.data[p].j;
            b->data[q].j = a.data[p].i;
            b->data[q].v = a.data[p].v;
            ++rownext[col]; //下一次再有该行元素,起始点就比上一个加了1
        }
    }
}

算法的时间复杂度为O(t)

带行表的三元组表

又称为行逻辑链接的顺序表。在按行优先存储的三元组表中,增加一个存储每一行的第一个非零元素在三元组表中位置的数组。
数据结构描述:

typedef struct
{
  TriTupleNode data[MaxSize];
 int RowTab[MaxRow];         //每行第一个非零元素的位置表
 int m,n,t;
}RLSMatrix;

特点:
① 对于任给行号i(0≤i≤m-1),能迅速地确定该行的第一个非零元在三元组表中的存储位置为RowTab[i]
② RowTab[i](0≤i≤m-1)表示第i行之前的所有行的非零元数。
③ 第i行上的非零元数目为RowTab[i+1]-RowTab[i](0≤i≤m-2)
④ 最后一行(即第m-l行)的非零元数目为t-RowTab[m-1](t为矩阵的非零元总数)

注意:
若在行表中令RowTab[m]=t(要求MaxRow>m)会更方便些,且t可省略。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

guangod

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值