数据结构和算法的重要性:
算法是程序的灵魂,优秀的程序可以在海量数据计算时,依然保持高速计算。
1. 数据结构和算法概述
数据data结构(structure)是一门研究组织数据方式的学科,有了编程语言也就有了数据结构。学好数据结构可以编写出更加漂亮,更加有效率的代码。
-
程序 = 数据结构 + 算法
-
数据结构是算法的基础, 换言之,想要学好算法,需要把数据结构学到位
2. 线性结构和非线性结构
数据结构包括:线性结构 和 非线性结构
2.1 线性结构
-
线性结构作为最常用的数据结构,其特点是 数据元素之间存在一对一 的线性关系。
-
线性结构有两种不同的存储结构,即 顺序存储结构(数组) 和 链式存储结构(链表)。顺序存储的线性表称为顺序表,顺序表 中的 存储元素是连续的(是指地址是连续的)。
-
链式存储的线性表称为链表,链表中的 存储元素不一定是连续的,元素节点中存放数据元素以及相邻元素的地址信息
-
线性结构常见的有:数组、队列、链表和栈。
2.2 非线性结构
非线性结构包括:二维数组,多维数组,广义表,树结构,图结构。
3. 稀疏数组
介绍:
当一个数组中大部分元素为0,或者为同一个值的数组时,可以使用稀疏数组来保存该数组。
使用步骤:
- 第一行记录数组一共有几行几列,有多少个不同的值。
- 把具有不同值的元素的行列及值记录在一个小规模的数组中,从而缩小程序的规模。
例子:
原始数组:
转变为 稀疏数组:
分析:
第一行记录了原始数组一共有几行几列,有多少个不同的值。
后面的n行记录了各个值所在的行列位置及本身的数值。
应用实例:
-
使用稀疏数组,来保留类似前面的二维数组(棋盘、地图等等)
-
把稀疏数组存盘,并且可以从新恢复原来的二维数组数
-
整体思路分析(图解)
实现代码:
public class SparseArray1 {
public static void main(String[] args) {
// 创建一个原始的二维数组 11*11
// 0:表示没有棋子 1:表示黑子 2:表示蓝子
int chessArr1[][]=new int[11][11];
chessArr1[1][2]=1;
chessArr1[2][3]=2;
chessArr1[3][5]=2;
// 输出原始的二维数组
System.out.println("原始的二维数组:");
// for-each 循环遍历方式
// for (int row[]:chessArr1) {
// for (int data: row){
// System.out.printf("%d\t",data);
// }
// System.out.println();
// }
// 常规的 for 循环遍历方式
// 因为原始数组是11*11的二维数组,故chessArr1.length=11,chessArr1[1].length=11 遍历时可以直接替换成11即可
for(int i=0;i<chessArr1.length;i++){
for(int j=0;j<chessArr1[1].length;j++){
System.out.printf("%d\t",chessArr1[i][j]);
}
System.out.println();
}
// 将二维数组 转 稀疏数组
// 1. 先遍历二维数组 得到 非0 数据的 个数
int sum=0;
for(int i=0;i<11;i++){
for(int j=0;j<11;j++){
if(chessArr1[i][j]!=0){
sum++;
}
}
}
// 2. 创建对应的稀疏数组
// 一共有sum+1行(第一行记录原始数组一共有几行几列,有多少个不同的值;后面的n行记录了各个值所在的行列位置及本身的数值)
// 一共有3列(row、cel、val)
int sparseArr[][]=new int[sum+1][3];
// 给稀疏数组赋值
// 给第一行赋值
sparseArr[0][0]=11;
sparseArr[0][1]=11;
sparseArr[0][2]=sum;
// 遍历二维数组,将非0的值存放到 sparseArr 中
int count=0; //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<sum+1;i++){
System.out.printf("%d\t%d\t%d\t\n",sparseArr[i][0],sparseArr[i][1],sparseArr[i][2]);
}
// // 将稀疏数组写入文件(相当于存盘功能)
// try {
// File writeFileName = new File("sparseArray.text"); // 这里写入文件用的是 相对路径,实际用绝对路径或相对路径都可以.。文件存在则直接写入,不存在则会新建一个
// writeFileName.createNewFile(); //创建新文件,有同名的文件的话直接覆盖
// //防止文件建立或读取失败,用catch捕捉错误并打印,也可以throw;
//
// FileWriter writer= new FileWriter(writeFileName);
// BufferedWriter out =new BufferedWriter(writer);
// for(int i=0;i<sum+1;i++){
// out.write(sparseArr[i][0]+"\t"+sparseArr[i][1]+"\t"+sparseArr[i][2]+"\n");
// }
// out.close(); // 把缓存区内容压入文件
// //不关闭文件会导致资源的泄露,读写文件都同理
// }catch (IOException e){
// e.printStackTrace();
// }
//
// // 读取文件(相当于读盘功能)
// try {
// String pathname="sparseArray.text";
// File filename = new File(pathname);
// InputStreamReader reader =new InputStreamReader( new FileInputStream(filename)); // 建立一个输入流对象reader
// BufferedReader br =new BufferedReader(reader); // 建立一个对象,它把文件内容转成计算机能读懂的语言
// String line ="";
//
// line = br.readLine();
// if(line!=null){
// // 读的第一行的数据
// //对字符串进一步处理
// int i=0;
// String arr1[]=line.split("\\s+");
// int arr2[]=new int[arr1.length];
// for (int j=0;j<arr1.length;j++){
// arr2[j]=Integer.valueOf(arr1[j]);
// }
// int arr3[][]=new int[arr2[2]+1][3];
// for(int j=0;j<3;j++){
// arr3[i][j]=arr2[j];
// }
// while (line!=null){
// line=br.readLine(); // 一次读入一行数据
// if(line!=null){
// i++;
// String arr[]=line.split("\\\t+");
// for (int j=0;j<arr1.length;j++){
// arr3[i][j]=Integer.valueOf(arr[j]);
// }
// }
// }
//
// System.out.println();
// System.out.println("读文件得到的稀疏数组:");
// for (int m=0;m<i+1;m++){
// System.out.printf("%d\t%d\t%d\t\n",arr3[m][0],arr3[m][1],arr3[m][2]);
// }
// }
// }catch (IOException e){
// e.printStackTrace();
// }
// 将稀疏数组 恢复成 原始的二维数组
// 1. 先读取稀疏数组的第一行,根据第一行的数据,创建原始的二维数组
int row=sparseArr[0][0];
int cel =sparseArr[0][1];
int chessArr2[][]=new int[row][cel];
// 2. 在读取稀疏数组后几行的数据,并赋给 原始的二维数组 即可
for (int i=1;i<sparseArr.length;i++){
row=sparseArr[i][0];
cel=sparseArr[i][1];
chessArr2[row][cel]=sparseArr[i][2];
}
// 输出恢复后的二维数组
System.out.println();
System.out.println("恢复后的二维数组:");
for(int i=0;i<chessArr2.length;i++){
for(int j=0;j<chessArr2[1].length;j++){
System.out.printf("%d\t",chessArr2[i][j]);
}
System.out.println();
}
}
}