因为该二维数组的很多值是默认值0,因此记录了很多没有意义的数据.->稀疏数组。
当一个数组中大部分元素为0,或者为同一个值的数组时,可以使用稀疏数组来保存该数组。
稀疏数组的处理方法是:
/**
* @author frx
* @version 1.0
* @date 2022/12/16 10:25
*/
public class SparseArray {
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;
System.out.println("原始的二维数组:");
//输出
for (int[] row : chessArr1) {
for (int data : row) {
System.out.printf("%d\t",data);
}
System.out.println();
}
//将二维数组 转 稀疏数组
//1. 先遍历二维数组得到非0数据个数
int sum = 0;
for (int i = 0; i < chessArr1.length; i++) {
for (int j = 0; j < chessArr1[i].length; j++) {
if(chessArr1[i][j] != 0){
sum++;
}
}
}
System.out.println("sum="+sum);
//2.创建对应的稀疏数组
int sparseArr[][] = new int[sum+1][3];
//给稀疏数组赋值
sparseArr[0][0] = 11;
sparseArr[0][1] = 11;
sparseArr[0][2] = sum;
//遍历二维数组,将非0的值存放到稀疏数组中
int count = 0;//count 用来记录是第几个非零数据
for (int i = 0; i < chessArr1.length; i++) {
for (int j = 0; j < chessArr1[i].length; j++) {
if(chessArr1[i][j] != 0){
count++;
sparseArr[count][0] = i;
sparseArr[count][1] = j;
sparseArr[count][2] = chessArr1[i][j];
}
}
}
//输出稀疏数组的形式
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]);
}
//将稀疏数组转为二维数组
//1.先读取稀疏数组的第一行,根据第一行的数据,创建原始的二维数组,比如上面的chessArr2 =int[11][11]
int chessArr2[][] = new int[sparseArr[0][0]][sparseArr[0][1]];
System.out.println("恢复后的数组:");
//2.在读取稀疏教组第二行的数据,并赋给原始的二维数组即可.
for (int i = 1; i <= sparseArr[0][2 ];i++) {
chessArr2[sparseArr[i][0]][sparseArr[i][1]] = sparseArr[i][2];
}
//输出原始数组
for (int[] row : chessArr2) {
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
sum=2
得到的稀疏数组为:
11 11 2
1 2 1
2 3 2
恢复后的数组:
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
Process finished with exit code 0
说下我的思路:
...
String filePath = "e:\\map.data.txt";
try {
BufferedWriter writer = new BufferedWriter(new FileWriter(filePath));
for (int[] row : sparseArr) {
for (int i : row) {
writer.write(new Integer(i).toString()+"\\");
}
writer.newLine();
}
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));
String line;
System.out.println("读取的内容为:");
while ((line=bufferedReader.readLine())!= null){
String[] endLine = line.split("\\\\");
for (int i = 0; i < endLine.length; i++) {
System.out.print(endLine[i]+"\t");
}
}
bufferedReader.close();
} catch (Exception e) {
e.printStackTrace();
}
...
银行排队的案例:
/**
* @author frx
* @version 1.0
* @date 2022/12/16 20:14
*/
public class ArrayQueueDemo {
public static void main(String[] args) {
//创建一个队列
ArrayQueue arrayQueue = new ArrayQueue(3);
char key = ' ';//接受用户的输入
Scanner scanner = new Scanner(System.in);
boolean loop = true;
//输出一个菜单
while (loop){
System.out.println("s(show):显示队列");
System.out.println("e(exit):退出程序");
System.out.println("a(add):添加数据到队列");
System.out.println("g(get):从队列里面取数据");
System.out.println("h(head):查看队列头的数据");
key = scanner.next().charAt(0);//接受一个字符
switch (key){
case 's':
arrayQueue.showQueue();
break;
case 'a':
System.out.println("输入一个数:");
int value = scanner.nextInt();
arrayQueue.addQueue(value);
break;
case 'g':
try {
int res = arrayQueue.getQueue();
System.out.printf("取出的数据是%d\n",res);
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 'h':
try {
int res = arrayQueue.headQueue();
System.out.printf("队列头的数据是%d\n",res);
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 'e':
scanner.close();
loop = false;
break;
default:
break;
}
}
System.out.println("程序退出.............");
}
}
//使用数组模拟队列-编写一个叫做ArrayQueue类
class ArrayQueue {
private int maxSize;//表示数组的最大容量
private int front;//队列头
private int rear;//队列尾
private int[] arr;//该数组用于存放数据
//创建队列构造器
public ArrayQueue(int maxSize) {
this.maxSize = maxSize;
arr = new int[maxSize];
front = -1;//指向队列头部,分析出front是指向队列的前一个位置
rear = -1;//指向队列尾部,指向队列尾的数据(即就是队列最后一个数据)
}
//判断队列是否满
public boolean isFull() {
return rear == maxSize - 1;
}
//判断队列是否为空
public boolean isEmpty() {
return rear == front;
}
//添加数据到队列
public void addQueue(int n) {
//判断队列是否满
if (isFull()) {
System.out.println("队列满,不能加入数据");
return;
}
rear++; // 让rear后移
arr[rear] = n;
}
//获取队列的数据,出队列
public int getQueue() {
//判断队列是否为空
if (isEmpty()) {
//通过抛出异常处理
throw new RuntimeException("队列空,不能取数据");
}
front++;//让front后移
return arr[front];
}
//显示队列的所有数据
public void showQueue() {
//遍历
if (isEmpty()) {
System.out.println("队列空的,没有数据");
return;
}
for (int i = 0; i < arr.length; i++) {
System.out.printf("arr[%d]=%d\n", i, arr[i]);
}
}
//显示队列的头数据,注意不是取出数据
public int headQueue() {
//判断
if (isEmpty()) {
throw new RuntimeException("队列空的,没有数据~");
}
return arr[front + 1];
}
}
s(show):显示队列
e(exit):退出程序
a(add):添加数据到队列
g(get):从队列里面取数据
h(head):查看队列头的数据
s
队列空的,没有数据
a
输入一个数:
10
a
输入一个数:
20
a
输入一个数:
30
a
输入一个数:
40
队列满,不能加入数据
s
arr[0]=10
arr[1]=20
arr[2]=30
h
队列头的数据是10
g
取出的数据是10
g
取出的数据是20
g
取出的数据是30
s
队列空的,没有数据
a
输入一个数:
10
队列满,不能加入数据
e
程序退出.............
Process finished with exit code 0
出现问题,数据虽然取出了,但是队列不能再进行添加数据,不能达到复用的效果
对前面的数组模拟队列的优化,充分利用数组.因此将数组看做是一个环形的。(通过取模的方式来实现即可)
(rear + 1) % maxSize == front
满]rear == front
[空]思路如下:
(rear +1) % maxsize = front
【满】rear == front
空(rear+ maxSize - front) % maxSize
// rear=16.我们就可以在原来的队列上修改得到,一个环形队列/**
* @author frx
* @version 1.0
* @date 2022/12/17 11:18
*/
@SuppressWarnings("{all}")
public class CircleArrayQueue {
public static void main(String[] args) {
System.out.println("测试数组模拟环形队列:");
//创建一个环形队列
CircleArray queue = new CircleArray(4);//说明设置4,其队列的有效最大数据是3
char key = ' ';//接受用户的输入
Scanner scanner = new Scanner(System.in);
boolean loop = true;
//输出一个菜单
while (loop){
System.out.println("s(show):显示队列");
System.out.println("e(exit):退出程序");
System.out.println("a(add):添加数据到队列");
System.out.println("g(get):从队列里面取数据");
System.out.println("h(head):查看队列头的数据");
key = scanner.next().charAt(0);//接受一个字符
switch (key){
case 's':
queue.showQueue();
break;
case 'a':
System.out.println("输入一个数:");
int value = scanner.nextInt();
queue.addQueue(value);
break;
case 'g':
try {
int res = queue.getQueue();
System.out.printf("取出的数据是%d\n",res);
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 'h':
try {
int res = queue.headQueue();
System.out.printf("队列头的数据是%d\n",res);
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 'e':
scanner.close();
loop = false;
break;
default:
break;
}
}
System.out.println("程序退出~");
}
}
class CircleArray {
private int maxSize;//表示数组的最大容量
private int front;//队列头
private int rear;//指向队列最后一个元素的后一个位置
private int[] arr;//该数组用于存放数据
public CircleArray(int arrMaxSize) {
maxSize = arrMaxSize;
arr = new int[maxSize];
}
//判断队列是否满
public boolean isFull() {
return (rear + 1) % maxSize == front;
}
//判断队列是否为空
public boolean isEmpty() {
return rear == front;
}
//添加数据到队列
public void addQueue(int n) {
//判断队列是否满
if (isFull()) {
System.out.println("队列满,不能加入数据");
return;
}
arr[rear] = n;
// 让rear后移,必须考虑取模
rear = (rear + 1) % maxSize;
}
//获取队列的数据,出队列
public int getQueue() {
//判断队列是否为空
if (isEmpty()) {
//通过抛出异常处理
throw new RuntimeException("队列空,不能取数据");
}
//这里需要分析出 front 是指向队列的第一个元素
//1.先把 front 对应的值保存到一个临时变量
//2.将 front 后移,考虑取模
//3.将临时保存的变量返回
int value = arr[front];
front = (front + 1) % maxSize;
return value;
}
//显示队列的所有数据
public void showQueue() {
//遍历
if (isEmpty()) {
System.out.println("队列空的,没有数据");
return;
}
//思路:从front开始遍历,遍历多少个元素
//
for (int i = front; i < front + size(); i++) {
System.out.printf("arr[%d]=%d\n", i % maxSize, arr[i % maxSize]);
}
}
//求出当前队列有效数据的个数
public int size() {
//rear = 1
//front = 0
//maxSize = 3
return (rear + maxSize - front) % maxSize;
}
//显示队列的头数据,注意不是取出数据
public int headQueue() {
//判断
if (isEmpty()) {
throw new RuntimeException("队列空的,没有数据~");
}
return arr[front];
}
}
测试数组模拟环形队列:
s(show):显示队列
e(exit):退出程序
a(add):添加数据到队列
g(get):从队列里面取数据
h(head):查看队列头的数据
s
队列空的,没有数据
a
输入一个数:
10
a
输入一个数:
20
a
输入一个数:
30
a
输入一个数:
40
队列满,不能加入数据
s
arr[0]=10
arr[1]=20
arr[2]=30
g
取出的数据是10
s
arr[1]=20
arr[2]=30
a
输入一个数:
40
s
arr[1]=20
arr[2]=30
arr[3]=40
h
队列头的数据是20
g
取出的数据是20
g
取出的数据是30
g
取出的数据是40
s
队列空的,没有数据
a
输入一个数:
50
a
输入一个数:
60
s
arr[0]=50
arr[1]=60
a
输入一个数:
70
a
输入一个数:
80
队列满,不能加入数据
s
arr[0]=50
arr[1]=60
arr[2]=70
e
程序退出~
Process finished with exit code 0