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>### 运行结果<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>### 实现```javapublic 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());}}
运行结果
小结和优化
有一点技巧,增加个获取有效数据
