Java 数据结构与算法
该学习代码都在🔗上
数据结构
简介
数据结构包括:线性结构和非线性结构。
线性结构
- 线性结构作为最常用的数据结构,其特点是数据元素之间存在一对一的线性关系。
- 线性结构有两种不同的存储结构,即顺序存储结构和链式存储结构。顺序存储的线性表称为顺序表,顺序表中存储的元素是连续的(地址)。
- 链式存储的线性表称为链表。链表中的存储元素不一定是连续的(地址),元素节点中存放数据元素以及相邻元素的地址信息。
- 线性结构常见的有:数组,队列,链表和栈。
非线性结构
非线性结构包括:二维数组,多维数组,广义表,数结构,图结构等。
稀疏数组(sparse array)
简介
稀疏数组是对 当一个数组中大部分元素为同一个值的时候,对原数组进行压缩得到的数组,压缩过后的数组为稀疏数组。
示例
在一个五子棋程序中,有存盘退出,和续上盘的功能。
使用二维数组记录棋盘。(1-黑子, 2-白子)
问题:
因为该二维数组的很多值都是默认值0, 因此记录了很多没有意义的数据。
处理方法:
- 记录数组一共有几行几列,有多少个不同的值。
- 把具有不同值的元素的行列及值记录在一个小规模的数组中,从而缩小程序的规模。
如:
转换后的稀疏数组,第一行记录原数据的行树,列数,值的数量。而后每一行记录的都是每一个值的位置以及值。
二维数组转稀疏数组的思路
- 遍历 原始的二维数组,得到有效数据的个数 sum.
- 根据sum 就可以创建 稀疏数组 sparser[sum+1][3].
- 将二维数组的有效数据存入到稀疏数组。
稀疏数组转原始的二维数组的思路
- 先读取稀疏数组的第一行,根据第一行的数据,创建原始的二维数组。
- 遍历稀疏数组,根据稀疏数组的值,赋值给原始的二维数组
代码实现
- 先定义原始二维数组与格式化数组方法
public static void main(String[] args) {
// 初始化原始二维数组
int[][] chessArr = init();
toStringArr(chessArr);
}
/**
* 初始原始的二维数组,11 * 11
* 描述:0-没有棋子,1-黑子,2-白子
* @return
*/
public static int[][] init(){
int[][] chessArr = new int[11][11];
// 第二行第三列为黑子,第三行第四列为白子
chessArr[1][2] = 1;
chessArr[2][3] = 2;
return chessArr;
}
/**
* 输出二维数组
* @param arr
*/
public static void toStringArr(int[][] arr){
for (int[] row : arr) {
for (int data : row) {
System.out.printf("%d\t", data);
}
System.out.println();
}
}
打印如下:
0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0
0 0 0 2 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 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 0
- 定义稀疏数组基础方法
public static void main(String[] args) {
// 初始化原始二维数组
int[][] chessArr = init();
toStringArr(chessArr);
System.out.println("--------");
// 原始二维数组转为稀疏数组
int[][] sparseArr = chessArrConvertSparseArr(chessArr);
toStringArr(sparseArr);
}
/**
* 原始二维数组转为稀疏数组
* @param chessArr
* @return
*/
public static int[][] chessArrConvertSparseArr(int[][] chessArr){
// 1. 先进行初始化稀疏数组
int[][] sparseArr = initSparseArr(chessArr);
// 2. 赋值稀疏数组
int index = 1; // 定义下标,用于对稀疏数组赋值使用
for (int i = 0; i < chessArr.length; i++) {
for (int j = 0; j < chessArr[i].length; j++) {
if (chessArr[i][j] != 0){
sparseArr[index][0] = i; // 记录行下标
sparseArr[index][1] = j; // 记录列下标
sparseArr[index][2] = chessArr[i][j]; // 记录值
index++;
}
}
}
return sparseArr;
}
/**
* 初始化稀疏数组
* 注意:稀疏数组固定为3列
* @param chessArr 原始的二维数组
* @return
*/
public static int[][] initSparseArr(int[][] chessArr){
// 获取行数和列数
int row = chessArr.length;
int col = chessArr[0].length;
// 获取原始数组的有效值的数量
int validSum = getArrayValidSum(chessArr);
int[][] sparseArr = new int[validSum + 1][3];
sparseArr[0][0] = row;
sparseArr[0][1] = col;
sparseArr[0][2] = validSum;
return sparseArr;
}
/**
* 获取二维数组的有效的个数
* @param arr
* @return
*/
public static int getArrayValidSum(int[][] arr){
int sum = 0;
for (int[] row : arr) {
for (int data : row) {
if (data != 0){
sum++;
}
}
}
return sum;
}
稀疏数组打印如下:
11 11 2
1 2 1
2 3 2
结论:由原始的二维数组 11 * 11 转为 稀疏数组后为 3 * 3。其压缩所节约资源可观。
稀疏数组转为原始的二维数组
代码如下:
public static void main(String[] args) {
// 初始化原始二维数组
int[][] chessArr = init();
toStringArr(chessArr);
System.out.println("--------");
// 原始二维数组转为稀疏数组
int[][] sparseArr = chessArrConvertSparseArr(chessArr);
toStringArr(sparseArr);
System.out.println("==========");
// 稀疏数组转为原始的二维数组
int[][] chessArr1 = sparseArrConvertChessArr(sparseArr);
toStringArr(chessArr1);
}
/**
* 将稀疏数组转为原始的二维数组
* 1. 先读取稀疏数组的第一行,根据第一行的数据,创建原始的二维数组。
* 2. 遍历稀疏数组,根据稀疏数组的值,赋值给原始的二维数组
* @param sparseArr
* @return
*/
public static int[][] sparseArrConvertChessArr(int[][] sparseArr){
int row = sparseArr[0][0]; // 获取原始的二维数组的行数
int col = sparseArr[0][1]; // 获取原始的二维数组的列数
// 初始化原始的二维数组
int[][] chessArr = new int[row][col];
// 遍历稀疏数组,赋值给原始的二维数组, 过滤其第一条数据,因为第一条存储的是整个原始二维数据的结构
for (int i = 1; i < sparseArr.length; i++) {
chessArr[sparseArr[i][0]][sparseArr[i][1]] = sparseArr[i][2];
}
return chessArr;
}
打印如下:
0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0
0 0 0 2 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 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 0