第3章:稀疏数组和队列
稀疏数组
当一个数组中大部分元素为0,或者为同一个值的数组时,可以使用稀疏数组来保存该数组。
稀疏数组的处理方法是:
- 记录数组一共有几行几列,有多少个不同的值
- 把具有不同值的元素的行列及值记录在一个小规模的数组中,从而缩小程序的规模
二维数组转稀疏数组
- 遍历原始二维数组,得到有效数据个数sum
- 根据sum就可以创建稀疏数组
sparseArr int[sum+1][3]
- 将二维数组的有效数据存入到稀疏数组
稀疏数组转二维数组
- 读取稀疏数组第一行,根据第一行的数据,创建二维数组,
chessArr=new int[11][11]
- 再读取稀疏数组后几行的数据,赋给二维数组
//初始二维数组
int[][] chessArr1 = new int[11][11];
chessArr1[1][2]=1;
chessArr1[2][3]=2;
chessArr1[4][5]=2;
转为稀疏数组
//1.有多少个数
int sum=0;
for (int i = 0; i < 11; i++) {
for (int j = 0; j < 11; j++) {
if (chessArr1[i][j]!=0){
sum++;
}
}
}
//2.创建稀疏数组
int[][] sparseArr=new int[sum+1][3];
sparseArr[0][0]=11;
sparseArr[0][1]=11;
sparseArr[0][2]=sum;
//3.第几个非零数,每个数的信息放一行
int 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; //i和j表示第几行第几列
sparseArr[count][1]=j;
sparseArr[count][2]=chessArr1[i][j];
}
}
}
//遍历
for (int i = 0; i < sparseArr.length; i++) {
System.out.println(sparseArr[i][0]+"\t"+sparseArr[i][1]+"\t"+sparseArr[i][2]);
}
转为二维数组
//转为二维数组,保存非0数
int[][] chessArr2=new int[sparseArr[0][0]][sparseArr[0][1]];
for (int i = 1; i < sparseArr.length; i++) {
chessArr2[sparseArr[i][0]][sparseArr[i][1]]=sparseArr[i][2];
}
//遍历
for(int[] row:chessArr2){
for (int data:row){
System.out.print("\t"+data);
}
System.out.println();
}
练习:
- 在前面的基础上,将稀疏数组保存到磁盘上,比如 map.data
- 恢复原来的数组时,读取map.data 进行恢复
队列
使用数组模拟队列
- 数组只能使用一次,默认front=-1,rear=-1
- front指向元素前一个位置
- 出队列后数组中的元素并没有删除,只是front++了
public class ArrayQueue {
private int maxSize;
private int front;
private int rear;
private int[] arr;
public ArrayQueue(int arrMaxSize) {
maxSize = arrMaxSize;
arr = new int[maxSize];
front = -1;
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++;
arr[rear] = n;
}
//出队列
public int getQueue() {
if (isEmpty()) {
throw new RuntimeException("空");
}
front++; //front初始为-1,指向前一个元素
return arr[front];
}
//遍历显示
public void showQueue() {
if (isEmpty()) {
System.out.println("空");
return;
}
for (int i = arr.length-1; i >=0; i--) {
System.out.println("arr["+i+"]="+arr[i]);
}
}
//获取头数据,没有出队列
public int headQueue(){
if (isEmpty()){
throw new RuntimeException("空");
}
return arr[front+1];
}
}
环形队列
思路:
- front指向队列的第一个元素,arr[front]为第一个元素,初始front=0
- rear指向队列最后一个元素的后一个位置,空出一个作为约定,初始rear=0
- 队列满:
(rear+1)%maxSize=front
- 队列空:
(rear==front)
- 队列中有效数据个数:
(rear+maxSize-front)%maxSize
public class CircleArrayQueue {
private int maxSize;
private int front;
private int rear;
private int[] arr;
public CircleArrayQueue(int arrMaxSize){
maxSize=arrMaxSize;
front=0;
rear=0;
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+1)%maxSize;
}
public int getQueue(){
if (isEmpty()){
throw new RuntimeException("空");
}
int value=arr[front];
front=(front+1)%maxSize;
return value;
}
public void showQueue(){
if (isEmpty()){
System.out.println("空");
return;
}
for (int i = front; i < front+size(); i++) {
System.out.println("arr["+i%maxSize+"]="+arr[i%maxSize]);
}
}
//有效数据个数
public int size(){
return (rear+maxSize-front)%maxSize;
}
public int headQueue(){
if (isEmpty()){
throw new RuntimeException("空");
}
return arr[front];
}
}