【数据结构与算法】数据结构介绍与稀疏数组相关操作

一 数据结构介绍

1 数据结构和算法的重要性

  • 算法是程序的灵魂,优秀的程序可以在海量数据计算时,依然保持高速计算。
  • 一般来讲程序会使用了内存计算框架 ( 比如Spark ) 和缓存技术 ( 比如Redis等 ) 来优化程序,再深入的思考一下,这些计算框架和缓存技术, 它的核心功能是哪个部分呢?
  • 拿实际工作经历来说, 在Unix下开发服务器程序,功能是要支持上千万人同时在线, 在上线前,做内测,一切OK。可上线后,服务器就支撑不住了,公司的CTO对代码进行优化,再次上线,坚如磐石。就能感受到程序是有灵魂的,就是算法。
  • 目前程序员面试的门槛越来越高,很多一线IT公司(大厂),都会有数据结构和算法面试题。
  • 如果不想永远都是代码工人,那就花时间来研究下数据结构和算法。

2 数据结构和算法的关系

  • 数据结构(data structure)是一门研究组织数据方式的学科,有了编程语言也就有了数据结构.学好数据结构可以编写出更加漂亮,更加有效率的代码。
  • 要学习好数据结构就要多多考虑如何将生活中遇到的问题,用程序去实现解决.
  • 程序 = 数据结构 + 算法
  • 数据结构是算法的基础, 换言之,想要学好算法,需要把数据结构学到位。

3 线性结构和非线性结构

数据结构包括:线性结构非线性结构

(1)线性结构

  • 线性结构作为最常用的数据结构,其特点是数据元素之间存在一对一的线性关系。
  • 线性结构有两种不同的存储结构,即顺序存储结构和链式存储结构。
    • 顺序存储的线性表称为顺序表,顺序表中的存储元素是连续的。
    • 链式存储的线性表称为链表,链表中的存储元素不一定是连续的,元素节点中存放数据元素以及相邻元素的地址信息。
  • 线性结构常见的有:数组、队列、链表和栈。

(2)非线性结构

  • 其特点是数据元素之间存在一对多的非线性关系。
  • 非线性结构包括:二维数组,多维数组,广义表,树结构,图结构。

二 稀疏数组

1 应用场景

假如想要开发一个五子棋游戏,如果使用二维数组记录棋盘,将黑棋置为1,白棋置为2,会发现这样一个数组存在很多没有意义的默认值0,浪费很多空间,这时就可以使用稀疏数组。

  • 使用稀疏数组,来保留类似棋盘,地图等二维数组。
  • 把稀疏数组存盘,并且可以从新恢复原来的二维数组数。

2 基本概念

(1)基本介绍

当一个数组中大部分元素为0,或者为同一个值的数组时,可以使用稀疏数组来保存该数组。

非零元素远远少于矩阵元素的个数。

(2)压缩策略

稀疏数组的处理方法(压缩策略)是:

  • 压缩存储:记录数组一共有几行几列,有多少个不同的值。
  • 链式存储:把具有不同值的元素的行列及值记录在一个小规模的数组中,从而缩小程序的规模。

如下图是一个稀疏矩阵的示例:

在这里插入图片描述

a 压缩存储

针对上图稀疏数组,使用压缩存储策略:顺序存储——三元组 <行,列,值>。

存储形式如下图:

在这里插入图片描述

注意存储的行列值与数组的下标相差一。

b 链式存储

使用链式存储策略存储上图稀疏数组,存储成下图:其中行列值的下面分别存在两个指针,左指针和右指针,具体含义如图:

在这里插入图片描述

3 需求实现

(1)需求分析

使用普通数组实现上图中的数组,再将普通数组转化成上图的稀疏数组,最后从稀疏数组恢复成普通数组。

(2)思路分析

如果使用二维数组存储棋盘会浪费很多空间,所以采用稀疏数组进行优化。

a 二维数组转稀疏数组的思路
  • 遍历原始的二维数组,得到有效数据的个数 sum
  • 根据sum可以创建稀疏数组``sparseArr,数组大小为int[sum] [3]`(三列分别为压缩存储中对应的【行row、列col、值val】。
  • 将二维数组的有效数据数据存入到稀疏数组。
b 稀疏数组转原始的二维数组的思路
  • 先读取稀疏数组的第一行,根据第一行的数据,创建原始的二维数组。
  • 在读取稀疏数组后几行的数据时,赋给原始的二维数组。

(3)代码实现

a 普通数组 --> 稀疏数组
// 创建原始的二维数据
int orginalArr[][] = new int[5][6];
orginalArr[0][2] = 4;
orginalArr[0][5] = 5;
orginalArr[1][1] = 3;
orginalArr[1][3] = 9;
orginalArr[2][4] = 7;
orginalArr[3][1] = 2;
// 输出原始二维数组
System.out.println("==================输出原始二维数组==================");
for(int[] row : orginalArr){
    for(int date : row){
        System.out.print(date + " ");
    }
    System.out.println();
}

// 将二维数组转化成稀疏数组
// 遍历二维数组,得到非0数据的个数
int sum = 0;
for(int[] row : orginalArr){
    for(int date : row){
        if(date != 0){
            sum++;
        }
    }
}
// 创建对应的稀疏数组
int sparseArray[][] = new int[sum][3];
// 记录当前是第几个非0数据
int count = 0;
for(int i = 0; i < orginalArr.length; i++){
    for (int j = 0; j < orginalArr[0].length; j++){
        if(orginalArr[i][j] != 0){
            sparseArray[count][0] = i + 1;
            sparseArray[count][1] = j + 1;
            sparseArray[count][2] = orginalArr[i][j];
            count++;
        }
    }
}
// 输出稀疏数组
System.out.println("==================输出对应的稀疏数组==================");
System.out.println("i" + " " + "j" + " " + "v");
for(int i = 0; i < sparseArray.length; i++){
    System.out.print(sparseArray[i][0] + " ");
    System.out.print(sparseArray[i][1] + " ");
    System.out.print(sparseArray[i][2] + " ");
    System.out.println();
}

结果如下:

在这里插入图片描述

b 稀疏数组 --> 普通数组
    // 将稀疏数组恢复成原始数组
    System.out.println("==================输出恢复后的数组==================");
    int row = 0;
    int col = 0;
    int maxRowIndex = 0;
    int maxColIndex = 0;
    for(int i = 0; i < sparseArray.length;i++){
        if(sparseArray[i][0] >= maxRowIndex){
            maxRowIndex = sparseArray[i][0];
            row = maxRowIndex;
        }
        if(sparseArray[i][1] >= maxColIndex){
            maxColIndex = sparseArray[i][1];
            col = maxColIndex;
        }
    }
    // 创建数组
    int newOriginArr[][] = new int[row][col];
    // 为新数组赋值
    for(int i = 0; i < sparseArray.length; i++){
        newOriginArr[sparseArray[i][0] - 1][sparseArray[i][1] - 1] = sparseArray[i][2];
    }
    // 遍历输出
    for(int i = 0; i < newOriginArr.length; i++){
        for(int j = 0; j < newOriginArr[0].length; j++){
            System.out.print(newOriginArr[i][j] + " ");
        }
        System.out.println();
    }

结果如下:

在这里插入图片描述

注意:最后一行全为0的行没有被恢复。

4 完整代码

public class SparseArray {
    public static void main(String[] args) {
        // 创建原始的二维数据
        int orginalArr[][] = new int[5][6];
        orginalArr[0][2] = 4;
        orginalArr[0][5] = 5;
        orginalArr[1][1] = 3;
        orginalArr[1][3] = 9;
        orginalArr[2][4] = 7;
        orginalArr[3][1] = 2;
        // 输出原始二维数组
        System.out.println("==================输出原始二维数组==================");
        for(int[] row : orginalArr){
            for(int date : row){
                System.out.print(date + " ");
            }
            System.out.println();
        }

        // 将二维数组转化成稀疏数组
        // 遍历二维数组,得到非0数据的个数
        int sum = 0;
        for(int[] row : orginalArr){
            for(int date : row){
                if(date != 0){
                    sum++;
                }
            }
        }
        // 创建对应的稀疏数组
        int sparseArray[][] = new int[sum][3];
        // 记录当前是第几个非0数据
        int count = 0;
        for(int i = 0; i < orginalArr.length; i++){
            for (int j = 0; j < orginalArr[0].length; j++){
                if(orginalArr[i][j] != 0){
                    sparseArray[count][0] = i + 1;
                    sparseArray[count][1] = j + 1;
                    sparseArray[count][2] = orginalArr[i][j];
                    count++;
                }
            }
        }
        // 输出稀疏数组
        System.out.println("==================输出对应的稀疏数组==================");
        System.out.println("i" + " " + "j" + " " + "v");
        for(int i = 0; i < sparseArray.length; i++){
            System.out.print(sparseArray[i][0] + " ");
            System.out.print(sparseArray[i][1] + " ");
            System.out.print(sparseArray[i][2] + " ");
            System.out.println();
        }

        // 将稀疏数组恢复成原始数组
        System.out.println("==================输出恢复后的数组==================");
        int row = 0;
        int col = 0;
        int maxRowIndex = 0;
        int maxColIndex = 0;
        for(int i = 0; i < sparseArray.length;i++){
            if(sparseArray[i][0] >= maxRowIndex){
                maxRowIndex = sparseArray[i][0];
                row = maxRowIndex;
            }
            if(sparseArray[i][1] >= maxColIndex){
                maxColIndex = sparseArray[i][1];
                col = maxColIndex;
            }
        }
        // 创建数组
        int newOriginArr[][] = new int[row][col];
        // 为新数组赋值
        for(int i = 0; i < sparseArray.length; i++){
            if(sparseArray[i][2] != 0){
                newOriginArr[sparseArray[i][0] - 1][sparseArray[i][1] - 1] = sparseArray[i][2];
            }
        }
        // 遍历输出
        for(int i = 0; i < newOriginArr.length; i++){
            for(int j = 0; j < newOriginArr[0].length; j++){
                System.out.print(newOriginArr[i][j] + " ");
            }
            System.out.println();
        }
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

OneTenTwo76

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

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

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

打赏作者

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

抵扣说明:

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

余额充值