【Data Structure and Algorithm】Introduction to Data Structure and Operations Related to Sparse Arrays

A data structure introduction

1 The importance of data structures and algorithms

  • Algorithms are the soul of programs, and excellent programs can still maintain high-speed calculations when calculating massive amounts of data.
  • Generally speaking, the program will use memory computing framework (such as Spark) and caching technology (such as Redis, etc.) to optimize the program, and then think about it deeply, which part of the core function of these computing framework and caching technology?
  • Taking the actual work experience as an example, developing server programs under Unix, the function is to support tens of millions of people online at the same time. Before going online, do internal testing, everything is OK. But after it went online, the server couldn't support it anymore. The company's CTO optimized the code, and it went online again, which was as solid as a rock. You can feel that the program has a soul, which is the algorithm.
  • At present, the threshold for programmer interviews is getting higher and higher. Many first-tier IT companies (big factories) will have data structure and algorithm interview questions.
  • If you don't want to be a code worker forever, take the time to study data structures and algorithms.

2 The relationship between data structure and algorithm

  • Data structure (data structure) is a subject that studies the way of organizing data . With a programming language, there is also a data structure. Learning the data structure well can write more beautiful and efficient code.
  • To learn the data structure well, we must think more about how to solve the problems encountered in life with programs.
  • Program = data structure + algorithm
  • The data structure is the basis of the algorithm. In other words, if you want to learn the algorithm well, you need to learn the data structure in place.

3 Linear and nonlinear structures

Data structures include: linear structures and nonlinear structures .

(1) Linear structure

  • As the most commonly used data structure, the linear structure is characterized by a one-to-one linear relationship between data elements.
  • The linear structure has two different storage structures, namely sequential storage structure and chain storage structure.
    • A sequentially stored linear table is called a sequential table, and the storage elements in the sequential table are continuous.
    • The linear list of linked storage is called linked list. The storage elements in the linked list are not necessarily continuous. The element nodes store the address information of data elements and adjacent elements.
  • Common linear structures are: arrays, queues, linked lists, and stacks.

(2) Nonlinear structure

  • It is characterized by a one-to-many nonlinear relationship between data elements.
  • Non-linear structures include: two-dimensional arrays, multidimensional arrays, generalized tables, tree structures, and graph structures.

two sparse array

1 Application Scenarios

If you want to develop a backgammon game, if you use a two-dimensional array to record the board, set the black pieces to 1 and the white pieces to 2, you will find that there are many meaningless default values ​​of 0 in such an array, which wastes a lot of space. Sparse arrays can be used.

  • Use sparse arrays to keep two-dimensional arrays like chessboards, maps, etc.
  • Save the sparse array to disk, and restore the original two-dimensional array number.

2 Basic concepts

(1) Basic introduction

When most of the elements in an array are 0, or an array of the same value, you can use a sparse array to save the array.

The number of non-zero elements is far less than the number of matrix elements.

(2) Compression strategy

The processing method (compression strategy) of sparse arrays is:

  • Compressed storage: record how many rows and columns the array has, and how many different values ​​there are.
  • Chained storage: Record the rows, columns and values ​​of elements with different values ​​in a small-scale array, thereby reducing the size of the program.

The following figure is an example of a sparse matrix:

insert image description here

a compressed storage

For the sparse array in the above figure, use the compressed storage strategy: sequential storage - triple <row, column, value>.

The storage format is as follows:

insert image description here

Note that the stored row and column values ​​differ from the subscript of the array by one.

b chain storage

Use the linked storage strategy to store the sparse array in the above figure, and store it as the figure below: There are two pointers below the row and column values, the left pointer and the right pointer, the specific meanings are shown in the figure:

insert image description here

3 Requirement Realization

(1) Demand analysis

Use ordinary arrays to realize the arrays in the above figure, then convert the ordinary arrays into the sparse arrays in the above figure, and finally restore the sparse arrays to ordinary arrays.

(2) Thinking Analysis

If a two-dimensional array is used to store the chessboard, a lot of space will be wasted, so a sparse array is used for optimization.

a The idea of ​​converting two-dimensional array to sparse array

  • Traverse the original two-dimensional array to get the number of valid data sum.
  • According to sumcan create a sparse array ``sparseArr ,数组大小为int[sum] [3]` (the three columns are the corresponding [row row, column col, value val] in the compressed storage.
  • Store the valid data of the two-dimensional array into a sparse array.

b The idea of ​​converting sparse arrays to original two-dimensional arrays

  • First read the first row of the sparse array, and create the original two-dimensional array based on the data in the first row.
  • When reading the data of the last few rows of the sparse array, it is assigned to the original two-dimensional array.

(3) Code implementation

a Ordinary array --> sparse array

// 创建原始的二维数据
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();
}

The result is as follows:

insert image description here

b sparse array --> ordinary array

    // 将稀疏数组恢复成原始数组
    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();
    }

The result is as follows:

insert image description here

NOTE: Rows with all 0s in the last row are not restored.

4 complete code

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();
        }
    }
}

Guess you like

Origin blog.csdn.net/weixin_43923463/article/details/128500540