数据结构–稀疏数组

作者 : 开心源码 本文共1879个字,预计阅读时间需要5分钟 发布时间: 2022-05-13 共230人阅读

概述

稀疏数组也是一种数组(总是二维的),是一种多维数组的数组压缩技术。比方存在一个10 \times 10的数组,但是数组中只有3个元素,假如要存储的话需要占100个位置。由于数组的每个位置的元素都要存储,哪怕是0或者者null
\begin{array}{l:} & 0 & 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9\\ \hline 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0\\ 1 & 0 & 0 & 0 & \mathbf{5} & 0 & 0 & 0 & 0 & 0 & 0\\ 2 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0\\ 3 & 0 & \mathbf{3} & 0 & 0 & \mathbf{7} & 0 & 0 & 0 & 0 & 0\\ 4 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0\\ 5 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0\\ 6 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0\\ 7 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0\\ 8 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0\\ 9 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0\\ \end{array}

稀疏数组就是为理解决这个问题的。稀疏数组的第一行存储数组的维度信息以及有效元素数。剩余行存储有效元素所在的坐标和元素的值。如上二维数组,那么采用稀疏数组存储就是:

\begin{array}{l:l:} \text{row}& \text{col} & \text{value} \\ \hline 10 & 10 & 3 \\ 1 & 3 & 5 \\ 3 & 1 & 3 \\ 3 & 4 & 7 \\ \end{array}

稀疏数组的行数是:有效元素数+1;列数是:数组维度+1。假如是一个3维数组,那就需要4列来保存数据,由于有3列要保存元素的坐标。

从上面的例子我们可以看出,稀疏数组存储的数据所占用的位置要比二维数组小很多,上面的10 \times 10的数组占了100个位置,而使用稀疏数组后仅用了16个位置。

什么情况下才可以用稀疏数组

然而稀疏数组并不总是好的,从上面的例子中我们也看出来了,稀疏数组只适合于有效数据少,但是数组较大的情况。假设一个二维数组行是m列是nt个有效数据,那么稀疏数组的行数就是t+1,列数是3,所以只有在
3(t+1) < mn; \Longrightarrow t < \frac{mn}{3} - 1
时,使用稀疏数组才能有效的对数据进行压缩。对于上面10 \times 10的数组就是32,假如超过32个有效元素,使用稀疏数组反而会添加开销。

那么推广到多维数组,假设n维数组可以存储S个元素,数组中有t个有效元素。那么稀疏数组的行数就是t+1,列数是n+1。只有在
(t+1)(n+1) < S \Longrightarrow t < \frac{S}{n+1} - 1
对于一个3维可存放1000个元素的数组,只有当有效元素小于249时,适用稀疏数组才能起到节省空间的作用。

实现

以下列出Java中二维稀疏数组的实现。

package com.codestd.study.ds;/** * 稀疏数组 * * @author jaune * @since 1.0.0 */public class SparseArray {    /**     * 将一个二维数组转成稀疏数组     * @param arrs 二维数组     * @return 稀疏数组     */    public int[][] toSparse(int[][] arrs) {        //arrs.length;        int row = arrs.length, col = arrs[0].length, nums = 0;        for (int[] arr : arrs) {            for (int i : arr) {                if (i != 0) {                    nums++;                }            }        }        int[][] sparseArr = new int[nums + 1][3];        sparseArr[0][0] = row;        sparseArr[0][1] = col;        sparseArr[0][2] = nums;        int index = 1;        for (int i = 0; i < row; i++) {            for (int j = 0; j < col; j++) {                int num = arrs[i][j];                if (num != 0) {                    sparseArr[index][0] = i;                    sparseArr[index][1] = j;                    sparseArr[index][2] = num;                    index++;                }            }        }        return sparseArr;    }    /**     * 将一个稀疏数组转为二维数组     * @param sparseArr 稀疏数组,这里稀疏数组需要是一个二维数组的稀疏数组。     * @return 复原后的二维数组     */    public int[][] parse(int[][] sparseArr) {        int row = sparseArr[0][0],                col = sparseArr[0][1],                nums =  sparseArr[0][2];        int[][] arr = new int[row][col];        for (int i = 1; i <= nums; i++) {            int[] ints = sparseArr[i];            arr[ints[0]][ints[1]] = ints[2];        }        return arr;    }    /**     * 测试一下     * @param args     */    public static void main(String[] args) {        SparseArray sparseArray = new SparseArray();        int[][] arrs = new int[11][11];        arrs[2][3] = 10;        arrs[3][6] = 20;        int[][] sparseArr = sparseArray.toSparse(arrs);        System.out.println(sparseArr);        int[][] sourceArr = sparseArray.parse(sparseArr);        System.out.println(sourceArr);    }}

对于n \times n的二维数组,toSparse()的时间复杂度为O(2n^2) = O(n^2)(假如不知道这里为什么等于O(n^2)可以看看我个人博客上关于算法复杂度的文章)。parse()方法的时间复杂度是O(n),这个n是有效元素数(O(n+1) = O(n)

应用

如棋盘的保存。围棋或者者五子棋,要把棋盘上落子的信息保存起来。

说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » 数据结构–稀疏数组

发表回复