• 稀疏数组


    概述

      稀疏数组是指那些零元个数远大于非零元个数的数组,而稀疏数组的零元分布往往没有规律可循。最经典的例子就是棋盘,在保存棋局时,棋盘上棋子的数目往往不会布满整个棋盘。以中国象棋为例,棋盘为10*9,而棋子数为32,而且在走棋过程中还会减少棋子数。所以如果用整个数组来保存棋盘就会花费太多空间。这时就要对稀疏数组进行压缩存储。

      压缩存储的处理方法是:

      1. 创建一个小规模的二维数组,其列数为3,分别记录行、列、值。

      2. 第一行记录原数组的行数、列数,以及非零元个数。

      3. 之后每一行记录每一个非零元在原数组中的行位标、列位标和值。

      以这个棋盘为例:

      

      用两位数表示一个棋子:

      1. 个位数:1表示兵、卒;2表示炮、砲;3表示车;4表示马;5表示相、象;6表示仕、士;7表示帅、将。

      2. 十位数:1表示红方;2表示黑方。

      比如,黑方用2表示,将用7表示,所以黑方的将用27表示;红方用1表示,兵用1表示,所以红方的兵用11表示。

      用一个10*9的二维数组存储棋盘,则这个棋盘可以表示为:

      

      即二维数组board中,board[1][3]=27,board[1][4]=26,board[1][5]=11,board[2][2]=11,board[2][5]=26,board[8][4]=17。

      对该二维数组进行压缩:

      1. 一共需要存储6个棋子,所以压缩后数组为sparseBoard[7][3]。

      2. 第一行存储二维数组的行数、列数和棋子数,即sparseBoard[0]=10,sparseBoard[1]=9,sparseBoard[2]=6。

      3. 之后6条记录分别存取棋子。

      最终得到的结果为:

      

    代码实现

      压缩稀疏数组:

     1 public static int[][] compress(int[][] arr) {
     2     if (arr == null) return null;
     3     // 行数
     4     int m = arr.length;
     5     // 列数
     6     int n = arr[0].length;
     7     // 非零元个数
     8     int num = 0;
     9     for (int i = 0; i < m; i++) {
    10         for (int j = 0; j < n; j++) {
    11             if (arr[i][j] != 0) {
    12                 num++;
    13             }
    14         }
    15     }
    16     // 创建压缩后的数组,列数为3,行数为1+非零元个数
    17     int[][] cArr = new int[1 + num][3];
    18     // 第一行记录原数组的行数、列数,以及非零元个数
    19     cArr[0][0] = m;
    20     cArr[0][1] = n;
    21     cArr[0][2] = num;
    22     // 每一行记录每一个非零元在原数组中的行位标、列位标和值
    23     for (int i = 0, k = 1; i < m; i++) {
    24         for (int j = 0; j < n; j++) {
    25             if (arr[i][j] != 0) {
    26                 cArr[k][0] = i;
    27                 cArr[k][1] = j;
    28                 cArr[k][2] = arr[i][j];
    29                 k++;
    30             }
    31         }
    32     }
    33     return cArr;
    34 }
    compress

      将压缩后的数组还原为稀疏数组:

     1 public static int[][] recovery(int[][] cArr) {
     2     if (cArr == null || cArr[0].length != 3) return null;
     3     // 第一行的前两个单元存储了原二维数组的行数和列数
     4     int[][] arr = new int[cArr[0][0]][cArr[0][1]];
     5     // 将除第一行外每一行还原到二维数组中,每一行的前两个单元为行位标和列位标,第三个单元为元素值
     6     for (int i = 1; i <= cArr[0][2]; i++) {
     7         arr[cArr[i][0]][cArr[i][1]] = cArr[i][2];
     8     }
     9     return arr;
    10 }
    recovery

      测试:

      

      

      

  • 相关阅读:
    Linux初识(命令, 文件, 系统管理)
    【JavaScript学习整理】DOM对象(location history screen navigator)
    Charles进行HTTPS抓包(iOS为例)
    【JavaScript学习整理】js基础
    【css学习整理】浮动,清除
    【css学习整理】css基础(样式,语法,选择器)
    【html学习整理】meta,img,表格,表单
    【LeetCode】无重复字符的最长子串
    【html学习整理】常用标签
    【LeetCode】种花问题
  • 原文地址:https://www.cnblogs.com/lqkStudy/p/11505790.html
Copyright © 2020-2023  润新知