第 1 章 数据结构和算法概述
1.1数据结构和算法的关系
1)
数据
data
结构
(structure)
是一门
研究组织数据方式
的学科,有了编程语言也就有了数据结构
.
学好数据结构可以
编写出更加漂亮
,
更加有效率的代码。
2)
要学习好数据结构就要多多考虑如何将生活中遇到的问题
,
用程序去实现解决
.
3)
程序
=
数据结构
+
算法
4)
数据结构是算法的基础
,
换言之,想要学好算法,需要把数据结构学到位。
1.2线性结构和非线性结构
数据结构包括:线性结构和非线性结构。
1.2.1
线性结构
1)
线性结构作为最常用的数据结构,其特点是
数据元素之间存在一对一
的线性关系
2)
线性结构有两种不同的存储结构,即
顺序存储结构
(
数组
)
和
链式存储结构
(
链表
)
。顺序存储的线性表称为顺序
表,顺序表中的
存储元素是连续
的
3)
链式存储的线性表称为链表,链表中的
存储元素不一定是连续的
,元素节点中存放数据元素以及相邻元素的地
址信息
4)
线性结构常见的有:
数组、队列、链表和栈
,后面我们会详细讲解
.
1.2.2
非线性结构
非线性结构包括:二维数组,多维数组,广义表,
树结构,图结构
第 2 章 稀疏数组和队列
2.1 稀疏 sparsearray 数组
2.1.1
先看一个实际的需求
编写的五子棋程序中,有存盘退出和续上盘的功能。
分析问题
:
因为该二维数组的很多值是默认值
0,
因此记录了
很多没有意义的数据->
稀疏数组
。
稀疏数组可以看做是普通数组的压缩,
但是这里说的普通数组是值无效数据量远大于有效数据量的数组
2
.1.2
基本介绍
当一个数组中大部分元素为0,或者为同一个值的数组时,可以使用稀疏数组来保存该数组。
稀疏数组的处理方法是
:
1)
记录数组
一共有几行几列,有多少个不同
的值
2)
把具有不同值的元素的行列及值记录在一个小规模的数组中,从而
缩小程序
的规模
稀疏数组举例说明
第一排的值记录原始数组总共几行几列以及共有多少个数值
2
.1.3
应用实例
1)
使用稀疏数组,来保留类似前面的二维数组
(
棋盘、地图等等
)
2)
把稀疏数组存盘,并且可以从新恢复原来的二维数组数
3)
整体思路分析
二维数组转稀疏数组的思路
1. 遍历原始的二维数组,得到有效数据的个数 sum
2. 根据sum 就可以创 稀疏数组 sparseArr int[sum + 1] [3]
3. 将二维数组的有效数据数据存入到稀疏数组
稀疏数组转原始的二维数组的思路
1. 先读取稀疏数组的第一行,根据第一行的数据,创建原始的二维数组,比如上面的 chessArr2 = int [11][11]
2. 在读取稀疏数组后几行的数据,并赋给 原始的二维数组 即可
课后练习 要求: 在前面的基础上,将稀疏数组保存到磁盘上,比如 map.data 恢复原来的数组时,读取map.data 进行恢复
import java.io.*;
public class SparseArr {
public static void main(String[] args) throws IOException {
//创建一个原始的二维数组11*11
//0:表示没有棋子,1表示黑子 2表示蓝子
int chessArr1[][] = new int[11][11];
chessArr1[1][2] = 1;
chessArr1[2][4] = 2;
chessArr1[3][4] = 5;
//输出原始的二维数组
System.out.println();
System.out.println("输出原始的二维数组");
for (int[] row : chessArr1) {
for (int data :row){
System.out.printf("%d\t",data);
}
System.out.println();
}
//二维数组转稀疏数组
//遍历原始的二维数组,得到有效数据的个数 sum
int sum = 0;
for (int i = 0; i < 11; i++) {
for (int j = 0; j < 11; j++) {
if (chessArr1[i][j] != 0){
sum++;
}
}
}
//根据sum 就可以创建稀疏数组 sparseArr int[sum + 1] [3]
int sparseArr[][] = new int[sum+1][3];
//给稀疏数组赋值
sparseArr[0][0] = 11;
sparseArr[0][1] = 11;
sparseArr[0][2] = sum;
//将二维数组的有效数据数据存入到稀疏数组
int count = 0;//用于记录是第几个非零数据
for (int i = 0; i < 11; i++) {
for (int j = 0; j < 11; j++) {
if (chessArr1[i][j] != 0){
count++;
sparseArr[count][0] = i;
sparseArr[count][1] = j;
sparseArr[count][2] = chessArr1[i][j];
}
}
}
//输出稀疏数组的形式
System.out.println();
System.out.println("得到的稀疏数组为:");
for (int i = 0; i <sparseArr.length ; i++) {
System.out.printf("%d\t%d\t%d\t\n",sparseArr[i][0],sparseArr[i][1],sparseArr[i][2]);
}
System.out.println();
//稀疏数组转原始的二维数组的思路
// 1. 先读取稀疏数组的第一行,根据第一行的数据,创建原始的二维数组,比如上面的 chessArr2 = int [11][11]
// 2. 在读取稀疏数组后几行的数据,并赋给原始的二维数组即可,从第二行遍历开始
int chessArr2[][] = new int[sparseArr[0][0]][sparseArr[0][1]];
for (int i = 1; i < sparseArr.length ; i++) {
chessArr2[sparseArr[i][0]][sparseArr[i][1]] = sparseArr[i][2];
}
//输出原始二维数组
System.out.println();
System.out.println("输出恢复后的二维数组");
for (int[] row : chessArr2) {
for (int data :row){
System.out.printf("%d\t",data);
}
System.out.println();
}
//作业:将稀疏数组保存到磁盘上,比如 map.data 恢复原来的数组时,读取map.data 进行恢复
//将稀疏数组保存到磁盘上
System.out.println("将稀疏数组保存到磁盘并命名为map.data");
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("E:\\笔记\\map.data"), "UTF-8");
for(int i = 0; i < sparseArr.length; i++) {
osw.write(sparseArr[i][0] + "," + sparseArr[i][1] + "," + sparseArr[i][2] + ",");
}
osw.close();//关闭输出流
//读取磁盘中的map.data文件
System.out.println("读取磁盘中的map.data文件");
InputStreamReader isr = new InputStreamReader(new FileInputStream("E:\\笔记\\map.data"),"UTF-8");
StringBuffer sb = new StringBuffer();
while(isr.ready()) {
sb.append((char)isr.read());
}
isr.close();//关闭输入流
System.out.println("读取成功");
System.out.printf("从磁盘读取的字符串为:\n%s\n", sb.toString());//格式化输出
String[] sb1 = sb.toString().split(",");
int sum1 = (sb1.length)/3;
//根据sum 就可以创建稀疏数组 sparseArr int[sum + 1] [3]
int sparseArr1[][] = new int[sum1+1][3];
//给稀疏数组赋值
sparseArr1[0][0] = Integer.parseInt(sb1[0]);
sparseArr1[0][1] = Integer.parseInt(sb1[1]);
sparseArr1[0][2] = sum1;
int count1 = 0;//用于记录是第几个非零数据
for (int i = 3; i < sb1.length; i+=3) {
count1++;
sparseArr1[count1][0] = Integer.parseInt(sb1[i]);
sparseArr1[count1][1] = Integer.parseInt(sb1[i+1]);
sparseArr1[count1][2] = Integer.parseInt(sb1[i+2]);;
}
//输出还原后的稀疏数组的形式
System.out.println();
System.out.println("得到的还原后的稀疏数组为:");
for (int i = 0; i <sparseArr1.length ; i++) {
System.out.printf("%d\t%d\t%d\t\n",sparseArr1[i][0],sparseArr1[i][1],sparseArr1[i][2]);
}
System.out.println();
//稀疏数组转原始的二维数组的思路
int chessArr3[][] = new int[sparseArr1[0][0]][sparseArr1[0][1]];
for (int i = 1; i < sparseArr1.length ; i++) {
chessArr3[sparseArr1[i][0]][sparseArr1[i][1]] = sparseArr1[i][2];
}
//输出原始二维数组
System.out.println();
System.out.println("输出还原后的二维数组为:");
for (int[] row : chessArr3) {
for (int data :row){
System.out.printf("%d\t",data);
}
System.out.println();
}
}
}