线性结构与非线性结构
- 线性结构是最常用的数据结构,特点是数据元素之间存在一对一的线性关系
- 线性结构有两种不同的存储结构,即顺序存储结构和链式存储结构,顺序存储的线性表成为顺序表,顺序表中的存储元素是连续的
- 链式存储的线性表成为链表,链表中的存储元素不一定是连续的,元素节点中存放数据元素以及相邻元素的地址信息
- 线性结构常见的有:数组、队列、链表、栈
- 非线性结构包括二维数组、多维数组、广义表、树、图
稀疏数组
问题导入
在一个五子棋游戏的程序中,需要实现存盘退出和续上盘的功能,可以将棋盘上的黑子、白子、空格分别用三个数字代替,根据棋盘的长宽存入一个MN的二维数组中,**这就需要MN个数字的内存来存放**。
但是在棋盘中,大部分格子都是空格,少部分是黑子和白子,前面所述的方式存储了太多没有意义的数据,对于这种一个数组中大部分元素为同一个值时,就可以采用稀疏数组来对数组进行压缩存储
稀疏数组的构成
稀疏数组一共有三列
假设大部分元素都是0
- 第一行:第一列记录二维数组的行数,第二列记录二维数组的列数,第三列记录二维数组中与0不同的元素个数
- 后续行:第一列记录有效数据的行号,第二列记录有效数据的列号,第三列记录有效数据的值
稀疏数组的转换
二维数组转稀疏数组并存储
/**
* 将二维数组转换为稀疏数组存储
*
* @param originArray
* 原始的二维数组
* @param baseNum
* 二维数组中重复最多的数据
*/
private static String saveSparseArray(int[][] originArray, int baseNum) {
int lineNum = originArray.length;// 获得二维数组的行数
int columnNum = originArray[0].length;// 获得二维数组的列数
int sum = 0;// 有效数据的总数
// 1.遍历源二维数组,获得有效数据的个数,来构成稀疏数组的第一行
for (int i = 0; i < lineNum; i++) {
for (int j = 0; j < columnNum; j++) {
if (originArray[i][j] != baseNum) {
sum++;
}
}
}
int sparseArray[][] = new int[sum + 1][3]; // 创建稀疏数组
// 初始化稀疏数组的第一行
sparseArray[0][0] = lineNum;
sparseArray[0][1] = columnNum;
sparseArray[0][2] = sum;
int current = 0;// 记录当前存入的是第几个有效数据,对应存入稀疏数组的行号
// 2.再次遍历源二维数组,将有效数据记录到稀疏数组中
for (int i = 0; i < lineNum; i++) {
for (int j = 0; j < columnNum; j++) {
if (originArray[i][j] != baseNum) {
current++;
sparseArray[current][0] = i;// 数据的行号存入第一列
sparseArray[current][1] = j;// 数据的列号存入第二列
sparseArray[current][2] = originArray[i][j];// 数据值存入第三列
}
}
}
// // 打印稀疏数组
// System.out.println("得到的稀疏数组为");
// for(int i=0;i<sum+1;i++) {
// for(int j=0;j<3;j++) {
// System.out.print(sparseArray[i][j]+"\t");
// }
// System.out.println();
// }
// 3.保存稀疏数组
FileWriter writer = null;
String path = null;
try {
// 创建需要写入的文件
path = SparseArray.class.getResource("").getPath() + "sparseArray.txt";// 写入的文件路径
File sparseArrayFile = new File(path);
writer = new FileWriter(sparseArrayFile);
for (int i = 0; i < sum + 1; i++) {
for (int j = 0; j < 3; j++) {
writer.append(String.valueOf(sparseArray[i][j]) + "#");
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (writer != null) {
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
writer = null;
}
}
return path;
}
稀疏数组文件读取转换为二维数组
/**
* 获取存储的稀疏数组文件
*
* @param url
* 文件保存地址
*/
private static int[][] getSparseArray(String url) {
// 1.读取稀疏数组文件
int[][] sparseArray = null;
FileReader reader = null;
BufferedReader bufferReader = null;
try {
File sparseArrayFile = new File(url);
reader = new FileReader(sparseArrayFile);
// 创建缓冲区读取器
bufferReader = new BufferedReader(reader);
String[] strs = bufferReader.readLine().split("#");// 读取文件
// 初始化稀疏数组,行数为字符串数组长度除以三
sparseArray = new int[strs.length / 3][3];
int length = strs.length;
int current = 0;
for (int i = 0; i < length; i++) {
// 通过取模将数据依次赋值
sparseArray[current][i % 3] = Integer.parseInt(strs[i]);
// 赋值三个数据之后表示一行结束
if (i+1 % 3 == 0 && i > 0) {
current++;
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
reader = null;
}
}
// 2.通过稀疏数组第一行的数据初始化二维数组
int[][] resArray = new int[sparseArray[0][0]][sparseArray[0][1]];
for (int i = 1; i < sparseArray[0][2] + 1; i++) {
resArray[sparseArray[i][0]][sparseArray[i][1]] = sparseArray[i][2];
}
return resArray;
}