数据结构与算法 稀疏数组

稀疏数组

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

  • 把一个大部分元素为0的数组转化为稀疏数组的方法:

  1. 记录数组一共有几行几列,有多少个不同的值
  2. 把具有不同值的元素的行列及值记录在一个小规模的数组中,从而缩小程序的规模
    在这里插入图片描述

在这里插入图片描述

  • 稀疏数组的本质就是元素为三元组的数组。

  • 稀疏数组应用:

  1. 在科学与工程领域中求解线性模型时经常出现大型的稀疏矩阵。在使用计算机存储和操作稀疏矩阵时,经常需要修改标准算法以利用矩阵的稀疏结构。由于其自身的稀疏特性,通过压缩可以大大节省稀疏矩阵的内存代价。更为重要的是,由于过大的尺寸,标准的算法经常无法操作这些稀疏矩阵。

  2. 从描述我们可以知道,稀疏数组主要应用有压缩数据和优化数据结构。

  • 原数组转为稀疏数组的思路:
    因为我们需要知道要用多大的空间去存储原数组中的非0元素,并且在逆过程中重构原数组,所以我们应该知道原数组的行列,每个非0数组元素的行列位置以及值。
  1. 遍历原数组得到非0元素的个数n。
  2. 构造n + 1 (第一行储存原数组的行列和非0元素的个数)行,3 列的数组。
  3. 遍历将非0元素存入稀疏数组。

*代码实现:

public class SparseArrayDemo {
    /**
     * return a sparse array,but the array just have the first nonempty line which contains
     * the row and column number of original array and a number of nonempty elements.
     * @param originalArray
     * @return
     */
    static int [][] returnSEmptySparseArray(int [][] originalArray){
        //traverse the original array to get the number of nonempty value.
        int numberOfNonemptyValue = 0;
        for (int i = 0;i < originalArray.length;i ++){
            for(int j = 0;j < originalArray[0].length;j ++){
                if(originalArray[i][j] != 0){
                    ++ numberOfNonemptyValue;
                }
            }
        }
        int [][] emptySparseArray = new int[numberOfNonemptyValue + 1][3];
        emptySparseArray[0][0] = originalArray.length;
        emptySparseArray[0][1] = originalArray[0].length;
        emptySparseArray[0][2] = numberOfNonemptyValue;
        return emptySparseArray;
    }

    /**
     * return the sparse array
     * @param originalArray
     * @return
     */
    public static int [][] returnSparseArray(int [][] originalArray){
        int [][] emptySparseArray = returnSEmptySparseArray(originalArray);
        int count = 1;
        for(int i = 0;i < originalArray.length;i ++){
            for (int j = 0;j < originalArray[0].length;j ++){
                if(originalArray[i][j] != 0){
                    //read nonempty element into empty sparse array from original array.
                    emptySparseArray[count][0] = i;
                    emptySparseArray[count][1] = j;
                    emptySparseArray[count][2] = originalArray[i][j];
                    ++ count;
                }
            }
        }
        return emptySparseArray;
    }

    /**
     * convert the sparse array back to original array
     * @param sparseArray
     * @return
     */
    public static int [][] returnOriginalArray(int [][] sparseArray){
        if(sparseArray == null){
            return null;
        }
        int [][] originalArray = new int[sparseArray[0][0]][sparseArray[0][1]];
        for(int i = 1;i <= sparseArray[0][2];i ++){
            originalArray[sparseArray[i][0]][sparseArray[i][1]] = sparseArray[i][2];
        }
        return originalArray;
    }
}
  • 测试代码:
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

public class SparseArrayTest {
    private int [][] array = new int[10][10];

    @BeforeEach
    public void setUp(){
        array[1][1] = 1;
        array[7][8] = 1;
        array[2][1] = 1;
        array[9][9] = 1;
        array[7][7] = 1;
        array[2][9] = 1;
    }

    @Test
    public void testReturnSEmptySparseArray(){
        int [][] sparseArray = SparseArrayDemo.returnSEmptySparseArray(array);
        for(int i = 0; i < sparseArray.length;i ++){
            for(int j = 0;j < 3;j ++){
                System.out.print(sparseArray[i][j] + "  ");
            }
            System.out.println();
        }
    }

    @Test
    public void testReturnSparseArray(){
        int [][] sparseArray = SparseArrayDemo.returnSparseArray(array);
        for(int i = 0; i < sparseArray.length;i ++){
            for(int j = 0;j < 3;j ++){
                System.out.print(sparseArray[i][j] + "  ");
            }
            System.out.println();
        }
    }

    @Test
    public void testReturnOriginalArray(){
        int [][] sparseArray = SparseArrayDemo.returnSparseArray(array);
        int [][] originalArray = SparseArrayDemo.returnOriginalArray(sparseArray);
        for(int i = 0;i < originalArray.length;i ++){
            for(int j = 0;j < originalArray[0].length;j ++){
                System.out.print(originalArray[i][j] + "  ");
            }
            System.out.println();
        }
    }
}
  • 输出:
10  10  6  
0  0  0  
0  0  0  
0  0  0  
0  0  0  
0  0  0  
0  0  0  


10  10  6  
1  1  1  
2  1  1  
2  9  1  
7  7  1  
7  8  1  
9  9  1  


0  0  0  0  0  0  0  0  0  0  
0  1  0  0  0  0  0  0  0  0  
0  1  0  0  0  0  0  0  0  1  
0  0  0  0  0  0  0  0  0  0  
0  0  0  0  0  0  0  0  0  0  
0  0  0  0  0  0  0  0  0  0  
0  0  0  0  0  0  0  0  0  0  
0  0  0  0  0  0  0  1  1  0  
0  0  0  0  0  0  0  0  0  0  
0  0  0  0  0  0  0  0  0  1  

注意,稀疏数组元素的行列值是数组下标。

  • 这里我们添加一个测试把稀疏数组存入文件中,再读出来转换为原数组:
	@Test
    public void testSaveSparseArrayInFileAndReverse() throws IOException, ClassNotFoundException {
        int [][] sparseArray = SparseArrayDemo.returnSparseArray(array);
        File file = new File("./test.txt");
        if(!file.exists()){
            file.createNewFile();
        }
        //write the sparse array into a file.
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(file));
        objectOutputStream.writeObject(sparseArray);

        //read the sparse array from the file
        ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(file));
        sparseArray = (int[][]) objectInputStream.readObject();

        int [][] originalArray = SparseArrayDemo.returnOriginalArray(sparseArray);
        for(int i = 0;i < originalArray.length;i ++){
            for(int j = 0;j < originalArray[0].length;j ++){
                System.out.print(originalArray[i][j] + "  ");
            }
            System.out.println();
        }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章