1、线性表之数组-简介
1、数组-概述:
1-1、数组是一种连续存储线性结构[在内存中连续存储多个元素的结构,在内存中的分配也是连续的],元素类型相同,大小相等。
1-2、数组可以是多维的,通过使用整型索引值来访问他们的元素,用来存储固定大小元素的线性表。
1-3、对于指定下标的查找,时间复杂度为O(1);对于一般的插入删除操作, 涉及到数组元素的移动,其平均复杂度也为O(n)。
2、数组-优点
2-1、按照索引查询元素速度快
2-2、按照索引遍历数组方便
3、数组-缺点:
3-1、数组的大小固定后就无法扩容了
3-2、数组只能存储一种类型的数据
3-3、添加,删除的操作慢,因为要移动其他的元素(如果是添加删除末尾的话,那速度不慢)
4、数组-适用场景:
4-1、频繁查询,对存储空间要求不大,很少增加和删除的情况。
5、数组的常见应用:
5-1、ArrayList、LinkedList、Vector、
6、普通数据-举例Demo:
public static void main(String[] args) {
Integer[] integers = new Integer[10];
integers[0]=0;//王五
integers[1]=1;
integers[2]=2;
}
2.1、稀疏数组(SparseArray)
1、稀疏数组(SparseArray)-介绍:
1-1、当一个数组中大部分元素为0,或元素值为同一个时,可使用稀疏数组来保存该数组
1-2、处理方式:
1-2-1、记录数组一共有几行几列、有多少个不同的值。
1-2-2、把具有不同值的元素的行列及值记录在一个小规模的数组中,从而缩小程序的规模。
1-3、代码示例
第一行存储原始数据总行数,总列数,总的非0数据个数
接下来每一行都存储非0数 所在行,所在列,和具体值
rows cols n
r1 c1 val1
r2 c2 val2
. . .
. . .
rn cn valn
2.2、普通数组与稀疏数组互转
public class SparseArray {
/**
* 稀疏数组可以简单的看作为是压缩,在开发中也会使用到。比如将数据序列化到磁盘上,减少数据量,在IO过程中提高效率等等。
* @param args
*/
public static void main(String[] args) throws Exception {
/**
* 初始化二维数组
* <p>
* 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 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
* </p>
*/
//初始化原数组,[row][col]
int[][] originalArray = new int[11][11];
originalArray[1][2] = 1;
originalArray[2][4] = 2;
for(int[] row : originalArray){
for(int item : row){
System.out.printf("%d\t",item);
}
System.out.println();
}
System.out.println("---------> 二维数组转稀疏数组");
/**
* 稀疏数组
* <p>
* 11 11 2
* 1 2 1
* 2 4 2
* </p>
*/
//得到非0数据数
int sum = 0;
for (int i = 0;i<originalArray.length;i++){
for(int j = 0;j<originalArray[i].length;j++){
if(originalArray[i][j] != 0){
sum++;
}
}
}
//创建稀疏数组
int[][] sparseArray = new int[sum+1][3];
//给稀疏数组赋值
sparseArray[0][0] = 11;
sparseArray[0][1] = 11;
sparseArray[0][2] = sum;
//将非0的数放入稀疏数组
//count:标识第几个非0数
int count = 0;
for (int i = 0;i<11;i++){
for(int j = 0;j<11;j++){
if(originalArray[i][j] != 0){
count++;
sparseArray[count][0] = i;
sparseArray[count][1] = j;
sparseArray[count][2] = originalArray[i][j];
}
}
}
//遍历稀疏数组
for(int i = 0;i<sparseArray.length;i++){
System.out.printf("%d\t%d\t%d\t\n",sparseArray[i][0],sparseArray[i][1],sparseArray[i][2]);
}
System.out.println("----------->稀疏数组转回原始数组");
// 将稀疏数组存入磁盘(文件)
sparseArrayToIo(sparseArray);
//将稀疏数组 恢复成原始的二维数组
//先读取稀疏数组的第一行 根据第一行创建原始的二维数组 比如上面的chessArr2=int[11][11]
//读取稀疏数组后 几行的数据 并赋给原始的二维数组
int newArray[][]=new int[sparseArray[0][0]][sparseArray[0][1]];
for(int i=1;i<=count;i++){
newArray[sparseArray[i][0]][sparseArray[i][1]]=sparseArray[i][2];
}
System.out.println("打印读取出来的二维数组");
for(int i=0;i<newArray.length;i++) {
for (int j = 0; j < newArray[i].length; j++) {
System.out.printf("%d\t", newArray[i][j]);
}
System.out.println();
}
}
/**
* 将稀疏数组存入磁盘(文件)
*
*/
public static void sparseArrayToIo(int[][] sparseArray) throws Exception {
OutputStreamWriter ow = null;
String filePath = "D:\\IdeaSelfLearnSpace\\DataStructureStudy\\sparseArray.txt";
File file = new File(filePath);
try {
if(!file.exists()){
file.createNewFile();
}
ow = new OutputStreamWriter(new FileOutputStream(filePath),"UTF-8");
//设置文件内容往后追加,默认为false
//bw = new BufferedWriter(new FileWriter(file, true));
//写入
for(int i =0; i < sparseArray.length; i++) {
for(int j = 0; j < sparseArray[i].length; j++) {
ow.write(sparseArray[i][j]+" ");
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭流
try {
if(ow != null){
ow.flush();
ow.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
2.3、数组-相关问题-列举
1、为什么大多数编程语言中,数组要从0开始编号,而不是1开始呢?
1-1、答:-- 下标即为 偏移量(offset),
假设a代表数组首地址,a[0]=偏移量为0的位置,即首地址,那么a[k]=偏移量k个type_size的位置,
a[k]地址公式为:a[k]_address = base_address + k * type_size
假设数组从 1 开始计数,那我们计算数组元素,a[k] 的内存地址就会变为:a[k]_address = base_address + (k-1)*type_size
1-2、问题总结:从 1 开始编号,每次随机访问数组元素都多了一次减法运算,对CPU来说就是多了一次减法指令。