【数据结构】串与数组(三)

简介: 【数据结构】串与数组

4.5.4 特殊矩阵概述


  • 特殊矩阵:具有相同的数据或0元素,且数据分布具有一定规律。
  • 分类:
  • 对称矩阵
  • 三级矩阵
  • 对角矩阵
  • 特殊矩阵只有部分有数据,其他内容为零,使用内存中一维空间(一片连续的存储空间)进行存储时,零元素没有必要进行存储,通常都需要进行压缩存储。
  • 压缩存储:多个值相同的矩阵元素分配同一个存储空间,零元素不分配存储空间。
  • 存储有效数据,零元素和无效数据不需要存储。
  • 不同的举证,有效和无效定义不同。

4.5.5 对称矩阵压缩存储【重点】


1)定义及其压缩方式

  • 什么是对称矩阵:a(i,j) = a(j,i)

image.png

对称矩阵的压缩方式:共4种

  1. 下三角部分以行序为主序存储的压缩【学习,掌握】

image.png

image.png

image.png

image.png

image.png

2)压缩存放及其公式

  • 压缩后存放到一维空间(连续的存放空间中)
    image.png
  • 对称矩形 A(i,j) 对应 一维数组 s[k] , k与i和j 公式:

image.png

3)练习

  • 练习1:

image.png

a(8,5)  -->索引库1,1表示方式

需要将1,1转化成0,0方式,从而可以使用公式,i和j同时-1

a(7,4)  -->索引库0,0表示方式

因为:i >= j

k= i(i+1)/2 +j = 7 * 8 / 2 + 4 = 32

32为索引为0的一维数组的下标

数据b下标是从1开始,对应的下标 32+1=33

image.png

b[13] 下标从1开始,归零

b[12] 下标从0开始,k=12

i*(i+1)/2 , 如果i=4,结果为10

12-10 = j

下标0,0时,a(4,2)

下标1,1时,a(5,3)

4.5.6 三角矩阵


1)概述&存储方式

  • 三角矩阵分为:上三角矩阵、下三角矩阵
  • 上三角矩阵:主对角线(不含主对角线)下方的元素值均为0。只在上三角的位置进行数据存储

image.png

image.png

  • 存储方式:三角矩阵的存放方式,与对称矩阵的存放方式相同。

2)上三角矩阵

  • 上三角矩阵实例

image.png

image.png

3)下三角矩阵

  • 下三角矩阵实例

image.png

下三角矩阵对应一维数组存放下标,计算公式

image.png

4.5.7 对角矩阵


1) 定义&名词

  • 对角矩阵:矩阵的所有非零元素都集中在以主对角线为中心的带状区域中,即除主对角线上和直接在主对角线上、下方若干条对角线上的元素之外,其余元素皆为零。

image.png

名词:

  • 半带宽:主对角线一个方向对角线的个数,个数为d。
  • 带宽:所有的对角线的个数。个数为 2d+1
  • n阶2d+1对角矩阵非零元素个数:n(2d+1) - d(d+1)
  • n(2d+1) :下图中所有颜色的个数
  • d(d+1)/2 :右下方浅蓝色三角的个数
  • d(d+1) :2个三级的个数(右下方、左上方)

image.png

  • 一维数组存储个数:n(2d+1) ,若某行没有2d+1个元素,则0补足。

2)压缩存储

image.png

image.png

4.6 稀疏矩阵


4.6.1 定义&存储方式


  • 稀疏矩阵:具有较多的零元素,且非零元素的分布无规律的矩阵。
    image.png
  • 稀疏因子:用于确定稀疏矩阵个数指标


image.png

  • 常见的2种存放方式:三元组表存储、十字链表存储

4.6.2 三元组表存储


1) 概述

  • 使用三元组唯一的标识一个非零元素
  • 三元组组成:row行、column列、value值
  • 三元组表:用于存放稀疏矩阵中的所有元素

image.png

2)相关类及其操作

三元组结点类publicclassTripleNode {   //三结点publicintrow;         //行号publicintcolumn;      //列号publicintvalue;       //元素值}
三元组顺序表类:publicclassSparseMatrix {         //稀疏矩阵publicTripleNode[] data;       //三元组表publicintrows;                //行数npublicintcols;                //列数mpublicintnums;                //非零元素的个数}
  • 三元组表初始化操作:

image.png

4.6.3 三元组表存储:矩阵转置


1)定义

  • 矩阵转置:一种简单的矩阵运算,将矩阵中每个元素的行列序号互换。
  • 特点:矩阵N[m×n] 通过转置 矩阵M[n×m]

image.png

image.png

image.png

/** this转置前的对象,每一个对象中都有一个data数据*   tm 转置后的对象,每一个对象中都有一个data数据* return 转置后的稀疏矩阵对象*/publicSparseMatrixtranspose() {       //转置// 1 根据元素个数,创建稀疏矩阵SparseMatrixtm=newSparseMatrix(nums);
// 2 设置基本信息tm.cols=rows;                 //2.1 行列交换tm.rows=cols;                 //2.2 列行交换tm.nums=nums;                 //2.3 元素个数// 3 进行转置intq=0;                                  //3.1 转置后数据的索引for(intcol=0 ; col<cols; col++) {     //3.2 转置之前数据数组的每一个列号for(intp=0; p<nums; p++) {        //3.3 依次获得转置前数据数组的每一个数据if (data[p].column==col) {        //3.4 获得指定列的数据tm.data[q].row=data[p].column;    //3.5 行列交换,值不变tm.data[q].column=data[p].row;
tm.data[q].value=data[p].value;
q++;                                //3.6 转置后的指针后移            }
        }
    }
// 4 返回转置后的稀疏矩阵returntm;
}
  • 矩阵转置时间复杂度:O(n×t) ,n列数,t非零个数

4.6.4 三元组表存储:快速矩阵转置


1)定义

  • 假设:原稀疏矩阵为N、其三元组顺序表为TN,N的转置矩阵为M,其对应的三元组顺序表为TM。
  • 快速转置算法:求出N的每一列的第一个非零元素在转置后的TM中的行号,然后扫描转置前的TN,把该列上的元素依次存放于TM的相应位置上。
  • 基本思想:分析原稀疏矩阵的数据,得到与转置后数据关系
  • 每一列第一个元素位置:上一列第一个元素的位置 + 上一列非零元素的个数
  • 当前列,原第一个位置如果已经处理,第二个将更新成新的第一个位置。

2)公式

  • 需要提供两个数组:num[]、cpot[]
  • num[] 表示N中第col列的非零元素个数
  • cpot[] 初始值表示N中的第col列的第一个非零元素在TM中的位置

image.png

3)算法:快速转置

publicSparseMatrixfasttranspose() {
// 1 根据元素个数,创建稀疏矩阵SparseMatrixtm=newSparseMatrix(nums);
// 2 设置基本信息tm.cols=rows;                 //2.1 行列交换tm.rows=cols;                 //2.2 列行交换tm.nums=nums;                 //2.3 元素个数// 3 校验if(num<=0) {
returntm;
    }
// 4 每一列的非零个数intnum=newint[cols];            //4.1 根据列数创建num数组for(inti=0; i<cols; i++) {      //4.2 初始数据(可省略)num[i] =0;
    }
for(inti=0; i<nums; i++) {     //4.3 遍历转置的数据intj=data[i].column;
num[j]++;
    }
// 5 转置后每一列第一个元素的位置数组intcpot=newint[cols];           // 5.1 位置的数组cpot[0] =0;                        // 5.2 第一列第一个元素为0for(inti=1; i<cols ; i++) {
cpot[i] =cpot[i-1] +num[i-1]; // 5.3 当前列第一个元素位置 = 上一列位置+个数    }
// 6 转置处理for(inti=0 ; i<nums ; i++) {
intj=data[i].column;             //6.1 转置前,每一个元素的列数intk=cpot[j];                    //6.2 转置后的位置tm.data[k].row=data[i].column;    //6.3 原数据 转置后 数据tm.data[k].column=data[i].row;
tm.data[k].value=data[i].value;
cpot[j]++;                          //6.4 下一个元素的位置    }
}
时间复杂度:O(n+t) ,n列数,t非零个数

4.6.5 十字链表存储


1)定义

  • 当稀疏矩阵中非零元素的位置或个数经常发生变化时,不宜采用三元组顺序表存储结构,而该用链式存储结构。
  • 十字链表结点由5个域组成:
  • row:所在行
  • column:所在列
  • value:非零元素值
  • right:存放与该非零元素==同行==的下一个非零元素结点指针。
  • down:存放与该非零元素==同列==的下一个非零元素结点指针。

image.png

image.png

2)相关类

结点类:classOLNode {
publicintrow, col;        //行号、列号publicintvalue;           //元素值publicOLNoderight;        //行链表指针publicOLNodedown;         //列链表指针}
十字链表类:classCrossList {
publicintmu, nu, tu;          //行数、列数、非零元素个数publicOLNode[] rhead, chead;   //行、列指针数组}
相关文章
【数据结构】数组、双链表代码实现
【数据结构】数组、双链表代码实现
|
1月前
|
数据处理 C语言 C++
数据结构第四弹---数组相关OJ题
数据结构第四弹---数组相关OJ题
|
5天前
|
存储 算法 调度
【数据结构与算法】详解循环队列:基于数组实现高效存储与访问
【数据结构与算法】详解循环队列:基于数组实现高效存储与访问
|
8天前
|
存储 JavaScript 前端开发
JavaScript中的数组是核心数据结构,用于存储和操作序列数据
【6月更文挑战第22天】JavaScript中的数组是核心数据结构,用于存储和操作序列数据。创建数组可以使用字面量`[]`或`new Array()`。访问元素通过索引,如`myArray[0]`,修改同样如此。常见方法包括:`push()`添加元素至末尾,`pop()`移除末尾元素,`shift()`移除首元素,`unshift()`添加到开头,`join()`连接为字符串,`slice()`提取子数组,`splice()`进行删除、替换,`indexOf()`查找元素位置,`sort()`排序数组。还有其他如`reverse()`、`concat()`等方法。
22 2
|
16天前
|
算法 索引 Python
数据结构 数组部分小结
数据结构 数组部分小结
|
24天前
|
存储 算法
数据结构和算法学习记录——设计循环队列(数组实现循环队列)核心思路、题解过程、完整题解
数据结构和算法学习记录——设计循环队列(数组实现循环队列)核心思路、题解过程、完整题解
17 1
|
5天前
|
存储 算法 编译器
【数据结构与算法】使用数组实现栈:原理、步骤与应用
【数据结构与算法】使用数组实现栈:原理、步骤与应用
|
6天前
|
存储 算法 Java
Java数据结构与算法:线性数据结构之数组
Java数据结构与算法:线性数据结构之数组
|
11天前
|
索引
栈的数组实现
栈的数组实现
6 0
|
1月前
|
存储 算法
【数据结构与算法 | 基础篇】[数组专题]力扣88
【数据结构与算法 | 基础篇】[数组专题]力扣88