002稀疏数组和队列[超大章]

本文介绍了稀疏数组的概念及其在处理大量零值或相同值的二维数组时的优势。通过记录不同元素的数量和位置,将大数组压缩为小规模的稀疏数组。此外,还展示了如何在Java和Python中实现二维数组到稀疏数组的转换以及反向转换。这种数据结构优化在节省存储空间和提高运算效率方面具有重要意义。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

稀疏数组和队列

稀疏数组

假设我们有一个棋盘

棋盘

我们可以看到,现在只有两个棋子在我们的棋盘上,虽然我们可以完全使用二维数组来保存整张棋盘,但是这样实在是太浪费空间了,这个时候我们就需要稀疏数组

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

稀疏数组的处理方法是:

  1. 记录数组一共有几行几列,有多少个不同的值

  2. 把具有不同值的元素的行列及值记录在一个小规模的数组中,从而缩小程序的规模

处理图解

可以看到,我们可以使用一种全新的方式来保存数组

  1. 记录我们当前的数组里面有多少个不同的元素
  2. 标记处我们每个不同元素的位置

现在,一个 11 × 11 11 \times 11 11×11的二维数组就被我们缩减成了一个 3 × 3 3 \times 3 3×3的数组了

思路

二维数组 转 稀疏数组的思路

  1. 遍历 原始的二维数组,得到有效数据的个数num

  2. 根据num就可以创建稀疏数组sparseArr int[num + 1][3]1

  1. 将二维数组的有效数据存入稀疏数组

稀疏数组 转 原始数组的思路

  1. 先读取稀疏数组的第一行, 根据第一行的数据,创建原始的二维数组,比如上面的chessArr2= int[11][11]

  2. 在读取稀疏数组后几行的数据,并赋给原始的二维数组即可

JAVA版代码实现

创建一个棋盘

代码如下

public class SparseArray {
    public static void main(String[] args) {
        // 创建一个原始的二维数组11*11
        //0表示没有棋子,1表示黑子,2表示白子
        int chessArr1[][] = new int[11][11];
        chessArr1[1][2] = 1;
        chessArr1[2][3] = 2;

        // 输出棋盘
        for(int[] row : chessArr1){
            for(int data : row){
                System.out.print(data + ",");
            }
            System.out.println();
        }
    }
}

输出结果

把代码内不一样的部分转化成稀疏数组

// 计算二维数组中不同元素的个数然后返回相应的位置
public int countDifferent(int[][] chessArr){

  int availableNumber = 0;
  for(int y = 0;y<chessArr.length;y++){
      for(int x = 0;x<chessArr[y].length;x++){
          if(chessArr[y][x] !=0 ){
              availableNumber++;
          }
      }
  }
  return availableNumber;
}

// 创建对应的稀疏数组
public int[][] createSpareArr(int[][] chessArr){
  // 获取我们一共有多少元素不同
  int differentElement = countDifferent(chessArr);

  // 创建一个需要返回的稀疏数组
  int spareArr[][] = new int[differentElement + 1][3];

  // 给稀疏数组赋值
  int id = 0;
  for(int y = 0;y<chessArr.length;y++){
      for(int x = 0;x<chessArr[y].length;x++){

          // 发现新的数据
          if(chessArr[y][x] !=0 ){
              if(id==0){
                  // 给我们的稀疏数组创建棋盘的基础信息
                  spareArr[0][0] = chessArr[y].length;
                  spareArr[0][1] = chessArr.length;
                  spareArr[0][2] = differentElement;

                  // 因为我们的赋值操作放在了数组里面,所以覆盖了原来应该存的数据
                  // 所以我们数组中的第一行和第二行是特别的,需要手动处理
                  spareArr[1][0] = x;
                  spareArr[1][1] = y;
                  spareArr[1][2] = chessArr[y][x];

                  id++;
              }else{
                  spareArr[id][0] = x;
                  spareArr[id][1] = y;
                  spareArr[id][2] = chessArr[y][x];
              }
              id++;
          }
      }
  }
return spareArr;
}

这么多代码我们一共干了些什么事情呢?

  1. 创建了一个专门操控棋盘的class
  2. 创建了一个方法createSpareArr,能返回棋盘打包之后的数组(稀疏数组)

把稀疏数组转换成真正的数据

public int[][] spareArrToNormalArr(int[][] spareArr){
        // 读取稀疏数组中的第一行数据来创建数列
        int[][] chessArr2 = new int[spareArr[0][0]][spareArr[0][1]];

        // 根据数据来依次恢复我们的数组
        for(int i=1;i<spareArr.length;i++){
            chessArr2[spareArr[i][1]][spareArr[i][0]] = spareArr[i][2];
        }
        return chessArr2;
    }

恢复的数据

可以看到我们现在的数据已经恢复了

  1. 先读取稀疏数组的第一行,根据第一行的数据,创建原始的二维数组

  2. 在读取稀疏数组后几行的数据,并赋给原始的二维数组即可。

Python版本代码实现

同理,我们也可以使用Python代码来复盘这些操作,但是无疑代码量会减少很多

创建棋盘

# 创建一个原始的二维数组11*11
# 0表示没有棋子,1表示黑子,2表示白子
self.chess_arr = []
temp_row = []
for y in range(11):
   for x in range(11):
       temp_row.append(0)
   self.chess_arr.append(temp_row)
   # 循环之后及得把temp_row清零
   temp_row = []

当然这些代码亦可以使用python的列表推导式

# 列表推导式只需要一行就可以搞定
self.chess_arr = [[0 for _ in range(11)] for _ in range(11)]

推导式的输出结果

设置棋盘上的棋子

# 设置放置棋子
def set_chess(self, *args):
  # 目前传入的坐标为(x,y)的形式
    for i in args:
        self.chess_arr[i[1]][i[0]] = i[2]


a.set_chess([0, 1, 2], [1, 1, 1])

设置棋子

创建稀疏数组

def get_chess_arr(self):
    return self.chess_arr

def create_spare_arr(self, chess_arr):
    available_number = 0
    spare_arr = []
    for y in range(len(chess_arr)):
        for x in range(len(chess_arr[y])):
            if chess_arr[y][x] != 0:
                available_number += 1
                spare_arr.append([x, y, chess_arr[y][x]])
    # 所有输出结束之后,在稀疏数组的头部插入列表信息
    spare_arr.insert(0, [len(chess_arr[y]), len(chess_arr), available_number])
    print(available_number)

    for i in spare_arr:
        print(i)

python输出结果

把稀疏数组转换成正常数组

def spare_to_list(self, spare_arr):
    restore_arr = [[0 for _ in range(spare_arr[0][1])] for _ in range(spare_arr[0][0])]
    for i in range(1,len(spare_arr)):
        restore_arr[spare_arr[i][1]][spare_arr[i][0]] = spare_arr[i][2]

    return restore_arr

python的输出

可以看到此时,我们的python也完成了转化


  1. 为什么这里是spareArr int[num + 1][3]而不是spareArr int[num + 1]呢?
     
    因为我们需要的是一个二维数组,存入数量的同时还要存入数据的坐标以及状态,内容大概长这样:
     
    [ (x,y,棋子的颜色),(x,y,棋子的颜色) ] ↩︎

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值