数据结构——全篇1.1万字保姆级吃透串与数组(超详细)(三)

简介: 数据结构——全篇1.1万字保姆级吃透串与数组(超详细)(三)

6.稀疏矩阵


6.1定义&存储方式


稀疏矩阵:具有较多的零元素,且非零元素的分布无规律的矩阵。微信图片_20220531150118.png

稀疏因子:用于确定稀疏矩阵个数指标微信图片_20220531150124.png

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


6.2相关类及其操作


6.2.1概述


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

6.2.2相关类及其操作


三元组结点类

public class TripleNode { //三结点
    public int row;     //行号
    public int column;    //列号
    public int value;   //元素值
}

三元组顺序表类

public class SparseMatrix {     //稀疏矩阵
    public TripleNode[] data;   //三元组表
    public int rows;        //行数n
    public int cols;        //列数m
    public int nums;        //非零元素的个数
}

三元组表初始化操作微信图片_20220531150428.png

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


6.3.1定义


矩阵转置:一种简单的矩阵运算,将矩阵中每个元素的行列序号互换。


特点:矩阵N[m×n] 通过转置 矩阵M[n×m]


转置原则:转置前从左往右查看每一列的数据,转置后就是一行一行的数据。

微信图片_20220531150520.png

6.3.2算法分析


微信图片_20220531150524.png

6.3.3算法:转置


微信图片_20220531150533.png

/** this转置前的对象,每一个对象中都有一个data数据
*   tm 转置后的对象,每一个对象中都有一个data数据
* return 转置后的稀疏矩阵对象
*/
public SparseMatrix transpose() {   //转置
    // 1 根据元素个数,创建稀疏矩阵
    SparseMatrix tm = new SparseMatrix(nums);
    // 2 设置基本信息
    tm.cols = rows;         //2.1 行列交换
    tm.rows = cols;         //2.2 列行交换
    tm.nums = nums;         //2.3 元素个数
    // 3 进行转置
    int q = 0;                  //3.1 转置后数据的索引
    for(int col = 0 ; col < cols; col ++) {   //3.2 转置之前数据数组的每一个列号
        for(int p = 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 返回转置后的稀疏矩阵
    return tm;
}

矩阵转置时间复杂度:O(n×t) ,n列数,t非零个数


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


6.4.1定义


假设:原稀疏矩阵为N、其三元组顺序表为TN,N的转置矩阵为M,其对应的三元组顺序表为TM。


快速转置算法:求出N的每一列的第一个非零元素在转置后的TM中的行号,然后扫描转置前的TN,把该列上的元素依次存放于TM的相应位置上。


基本思想:分析原稀疏矩阵的数据,得到与转置后数据关系


每一列第一个元素位置:上一列第一个元素的位置 + 上一列非零元素的个数


当前列,原第一个位置如果已经处理,第二个将更新成新的第一个位置。


6.4.2公式


  • 需要提供两个数组:num[]、cpot[]
  • num[] 表示N中第col列的非零元素个数
  • cpot[] 初始值表示N中的第col列的第一个非零元素在TM中的位置
  • 公式:微信图片_20220531150824.png

6.4.3算法:快速转置


public SparseMatrix fasttranspose() {
    // 1 根据元素个数,创建稀疏矩阵
    SparseMatrix tm = new SparseMatrix(nums);
    // 2 设置基本信息
    tm.cols = rows;         //2.1 行列交换
    tm.rows = cols;         //2.2 列行交换
    tm.nums = nums;         //2.3 元素个数
    // 3 校验
    if(num <= 0) {
        return tm;
    }
    // 4 每一列的非零个数
    int num = new int[cols];      //4.1 根据列数创建num数组
    for(int i = 0; i<cols; i ++) {    //4.2 初始数据(可省略)
        num[i] = 0;
    }
    for(int i = 0; i< nums; i ++) {   //4.3 遍历转置的数据
        int j = data[i].column;
        num[j]++;
    }
    // 5 转置后每一列第一个元素的位置数组
    int cpot = new int[cols];     // 5.1 位置的数组
    cpot[0] = 0;            // 5.2 第一列第一个元素为0
    for(int i = 1; i < cols ; i ++) {
        cpot[i] = cpot[i-1] + num[i-1]; // 5.3 当前列第一个元素位置 = 上一列位置+个数
    }
    // 6 转置处理
    for(int i = 0 ; i < nums ; i ++) {
        int j = data[i].column;       //6.1 转置前,每一个元素的列数
        int k = 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非零个数


6.5十字链表存储


6.5.1定义


当稀疏矩阵中非零元素的位置或个数经常发生变化时,不宜采用三元组顺序表存储结构,而该用链式存储结构。


十字链表结点由5个域组成:


row:所在行


column:所在列


value:非零元素值


right:存放与该非零元素==同行==的下一个非零元素结点指针。


down:存放与该非零元素==同列==的下一个非零元素结点指针。

微信图片_20220531150952.png

 6.5.2相关类


结点类:

class OLNode {
    public int row, col;    //行号、列号
    public int value;     //元素值
    public OLNode right;    //行链表指针
    public OLNode down;     //列链表指针
}

十字链表类:


class CrossList {
    public int mu, nu, tu;      //行数、列数、非零元素个数
    public OLNode[] rhead, chead; //行、列指针数组
}
相关文章
|
1月前
|
存储 Java 程序员
数据结构之 - 深入了解数组数据结构
数据结构之 - 深入了解数组数据结构
36 6
|
1月前
|
存储 算法 搜索推荐
探索常见数据结构:数组、链表、栈、队列、树和图
探索常见数据结构:数组、链表、栈、队列、树和图
95 64
|
1月前
|
算法 程序员 索引
数据结构与算法学习七:栈、数组模拟栈、单链表模拟栈、栈应用实例 实现 综合计算器
栈的基本概念、应用场景以及如何使用数组和单链表模拟栈,并展示了如何利用栈和中缀表达式实现一个综合计算器。
27 1
数据结构与算法学习七:栈、数组模拟栈、单链表模拟栈、栈应用实例 实现 综合计算器
|
1月前
|
存储 算法 定位技术
数据结构与算法学习二、稀疏数组与队列,数组模拟队列,模拟环形队列
这篇文章主要介绍了稀疏数组和队列的概念、应用实例以及如何使用数组模拟队列和环形队列的实现方法。
20 0
数据结构与算法学习二、稀疏数组与队列,数组模拟队列,模拟环形队列
|
2月前
|
存储 Java
java数据结构,线性表顺序存储(数组)的实现
文章介绍了Java中线性表顺序存储(数组)的实现。线性表是数据结构的一种,它使用数组来实现。文章详细描述了线性表的基本操作,如增加、查找、删除、修改元素,以及其他操作如遍历、清空、求长度等。同时,提供了完整的Java代码实现,包括MyList接口和MyLinearList实现类。通过main函数的测试代码,展示了如何使用这些方法操作线性表。
|
4月前
|
存储
【数据结构OJ题】轮转数组
力扣题目——轮转数组
42 2
【数据结构OJ题】轮转数组
|
3月前
|
存储 Java 程序员
"揭秘HashMap底层实现:从数组到链表,再到红黑树,掌握高效数据结构的秘密武器!"
【8月更文挑战第21天】HashMap是Java中重要的数据结构,采用数组+链表/红黑树实现,确保高效查询与更新。构造方法初始化数组,默认容量16,负载因子0.75触发扩容。`put`操作通过计算`hashCode`定位元素,利用链表或红黑树处理冲突。`get`和`remove`操作类似地定位并返回或移除元素。JDK 1.8优化了链表转红黑树机制,提升性能。理解这些原理能帮助我们更高效地应用HashMap。
42 0
|
5月前
|
存储 算法 调度
【数据结构与算法】详解循环队列:基于数组实现高效存储与访问
【数据结构与算法】详解循环队列:基于数组实现高效存储与访问
|
4月前
|
机器学习/深度学习 存储 算法
数据结构与算法:数组的操作
数据结构与算法:数组的操作
下一篇
无影云桌面