1.稀疏数组
需求
五子棋游戏
要有存盘退出,续上盘的功能
第一步的抽象:把五子棋的某一时刻转换为二维数组
问题:里面有很多没有意义的数据
第二步的解决方法:抽象为稀疏数组(见下图)
介绍
画图
文字说明
当一个数组中大部分元素为0,或者为同一个值的数组时,可以使用稀疏数组来保存该数组。
稀疏数组的处理方法
- 记录数组一共有几行几列,有多少个不同的值
把具有不同值的元素的行列及值记录在一个小规模的数组中,从而缩小程序的规模
分析思路
1.数组转稀疏
2.稀疏转数组
代码实现
public class SparseArray {
public static void main(String[] args) {
//初始化数组
int[][] rawArray = new int[11][11];
rawArray[1][2] = 1;
rawArray[2][3] = 2;
rawArray[4][5] = 1;
showArray(rawArray);
int[][] sparseArray = array2Sparse(rawArray);
showArray(sparseArray);
int[][] convertArray = sparse2Array(sparseArray);
System.out.println("=============================================================");
showArray(convertArray);
}
//打印数组
public static void showArray(int[][] printArray) {
for (int[] ints : printArray) {
for (int val : ints) {
System.out.printf("%d\t", val);
}
System.out.println();
}
}
//二维数组转稀疏数组
public static int[][] array2Sparse(int[][] rawArray) {
int count = 0;
for (int[] ints : rawArray) {
for (int val : ints) {
if (val > 0) {
count++;
}
}
}
System.out.println("count:" + count);
int[][] sparseArray = new int[count + 1][3];//根据count 声明稀疏数组
sparseArray[0][0]=rawArray.length;
sparseArray[0][1]=rawArray[0].length;
sparseArray[0][2]=count;
int sparseRowIndex=0;//记录下稀疏的行
for (int row=0;row<rawArray.length;row++) {
for (int col=0;col<rawArray[0].length;col++) {
if (rawArray[row][col]>0) {
sparseRowIndex++;
sparseArray[sparseRowIndex][0]=row;
sparseArray[sparseRowIndex][1]=col;
sparseArray[sparseRowIndex][2]=rawArray[row][col];
}
}
}
return sparseArray;
}
//稀疏数组转二维数组
public static int[][] sparse2Array(int[][] sparseArray) {
int[][] array=new int[sparseArray[0][0]][sparseArray[0][1]];
for (int i = 1; i < sparseArray.length; i++) {
//i 代表 稀疏数组的行数
array[sparseArray[i][0]][sparseArray[i][1]] = sparseArray[i][2];
}
return array;
}
}
运行结果
思考小结
1.需要慢慢调试,慢慢改
2.转稀疏数组的时候要控制行和列,用原始for循环替代增强for循环
3.转二维数组的时候注意下标控制
4.写算法慢慢来不要急2.队列
需求
介绍
队列是一个有序列表,可以用数组或是链表来实现
- 遵循先入先出的原则。即:先存入队列的数据,要先取出。后存入的要后取出
2.1 简单队列
思路
- 队列本身是有序列表,若使用数组的结构来存储队列的数据,则队列数组的声明如下图,其中maxSize是该队列的最大容量。
- 因为队列的输出、输入是分别从前后端来处理,因此需要两个变量front及rear分别记录队列前后端的下标,front会随着数据输出而改变,而rear则是随着数据输入而改变
需要实现的方法:add get head show isfull isempty
代码实现
```java public class ArrayQueue { int size;//队列容量 int[] arr;//数组存放数据 int front;//队列头指针 int rear;//队列尾指针
public ArrayQueue(int size) {
this.size = size;
this.front=-1;
this.rear=-1;
arr = new int[size];
}
public void show(){
if (isEmpty()) {
System.out.println("队列空的,无法取数据");
return;
}
for (int i = 0; i < arr.length; i++) {
System.out.printf("a[%d]=%d\n",i,arr[i]);
}
}
public boolean isFull(){
return rear == size - 1;
}
public boolean isEmpty(){
return rear == front;
}
public void add(int val) {
if (isFull()) {
System.out.println("满了,无法添加");
return;
}
rear++;
arr[rear] = val;
}
public int get() {
if (isEmpty()) {
throw new RuntimeException("队列空的,无法取数据");
}
front++;
return arr[front];
}
public int head(){
if (isEmpty()) {
throw new RuntimeException("队列空的,无法取数据");
}
return arr[front+1];
}
public static void main(String[] args) {
ArrayQueue queue = new ArrayQueue(3);
queue.add(3);
System.out.println(queue.head());
queue.add(4);
System.out.println(queue.head());
queue.add(5);
System.out.println(queue.head());
queue.add(6);
queue.show();
System.out.println(queue.get());
System.out.println(queue.get());
System.out.println(queue.get());
System.out.println(queue.get());
}
}
<a name="uLAlp"></a>
### 运行结果
![image.png](https://cdn.nlark.com/yuque/0/2021/png/655064/1638846136792-3d423ba6-c9c0-42a3-bb8c-5799e467efc3.png#clientId=u2b8eacd7-ffa1-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=171&id=udf81d62d&margin=%5Bobject%20Object%5D&name=image.png&originHeight=341&originWidth=881&originalType=binary&ratio=1&rotation=0&showTitle=false&size=31997&status=done&style=none&taskId=u0bb02f16-ef88-490b-9bda-3fa68fdcf29&title=&width=440.5)
<a name="dBQyL"></a>
### 小结和优化
1. 目前数组使用一次就不能用,没有达到复用的效果
1. 将这个数组使用算法(**取模算法**),改进成一个**环形队列**
<a name="zpcVw"></a>
## 2.2 环形队列
<a name="iR5AL"></a>
### 思路
重复利用数组之前空出的位置<br />重新定义front rear重新定义isFull isEmpty<br />环形其实就是类似跑步套圈
<a name="OdTxW"></a>
### 实现
```java
public class CircleArrayQueue {
int size;//队列容量
int[] arr;//数组存放数据
int front;//队列头指针 指向第一个元素
int rear;//队列尾指针 指向最后一个元素前一个的位置
public CircleArrayQueue(int size) {
this.size = size;
arr = new int[size];
}
public void show() {
if (isEmpty()) {
System.out.println("队列空的,无法取数据");
return;
}
for (int i = front; i < front + size(); i++) {
System.out.printf("a[%d]=%d\n", i % size, arr[i % size]);
}
}
public boolean isFull() {
return (rear + 1) % size == front;//有一个空位不能加,预留空位
}
public boolean isEmpty() {
return rear == front;
}
public void add(int val) {
if (isFull()) {
System.out.println("满了,无法添加");
return;
}
arr[rear] = val;
rear = (rear + 1) % size;
}
public int get() {
if (isEmpty()) {
throw new RuntimeException("队列空的,无法取数据");
}
int val = arr[front];
front = (front + 1) % size;
return val;
}
public int size() {
return (rear + size - front) % size;
}
public int head() {
if (isEmpty()) {
throw new RuntimeException("队列空的,无法取数据");
}
return arr[front];
}
public static void main(String[] args) {
CircleArrayQueue queue = new CircleArrayQueue(4);
queue.add(3);
queue.add(4);
queue.add(5);
queue.show();
System.out.println(queue.get());
System.out.println(queue.get());
System.out.println(queue.get());
queue.add(6);
System.out.println(queue.head());
queue.add(7);
queue.add(8);
queue.show();
System.out.println(queue.head());
System.out.println(queue.get());
System.out.println(queue.get());
System.out.println(queue.get());
}
}
运行结果
小结和优化
有一点技巧,增加个获取有效数据