稀疏数组和队列
稀疏数组(sparseArray)
当一个数组大部分元素为0或者为同一个值的数组时,可以使用稀疏数组来保存该数组。(比如编写五子棋程序中,有存盘退出和续上盘的功能)
稀疏数组的处理方法是:
- 记录数组一共有几行几列以及有多少个不同的值
- 把具有不同值的元素的行列及值记录在一个小规模的数组中,从而缩小程序的规模

基本思路:
二维数组转稀疏数组:
- 遍历二维数组,得到有效数据的个数sum
- 根据有效个数sum生成一个稀疏数组 sparseArr int[sum+1][3]
- 将二维数组的有效数据存入到稀疏数组中
稀疏数组转二维数组:
- 先读取稀疏数组的第一行(row:sparseArr[0][0],column:sparseArr[0][1]),根据第一行创建原始的二维数组,origialArr = int[row][column]
- 在读取稀疏数组后几行数据,并赋给原始的二维数据
public class SparseArray { public static void main(String[] args) { // 创建一个原始的二维数组 11*11 //0:表示没有棋子,1表示黑子 2表示蓝子 int[][] originalArr= new int[11][11]; originalArr[1][2] = 1; originalArr[2][3] = 2; //输出原始的二维数组 System.out.println("Original Array:"); for (int[] rows : originalArr) { for (int data : rows) { System.out.printf("%d\t",data); } System.out.println(); } //将原始数组转为稀疏数组 //1.先遍历二维数组 得到非0 数据的个数 int sum = 0; for (int i = 0; i < 11; i++) { for (int j = 0; j < 11; j++) { if (originalArr[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; for (int i = 0; i < 11; i++) { for (int j = 0; j < 11; j++) { if(originalArr[i][j]!=0) { count++; sparseArr[count][0] = i; sparseArr[count][1] = j; sparseArr[count][2] = originalArr[i][j]; } } } //打印稀疏数组 System.out.println(); 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]); } System.out.println(); //稀疏数组转原始数组 System.out.println("SparseArray lenth:"+ sparseArr.length); int row = sparseArr[0][0]; int column = sparseArr[0][1]; int[][] origiArr = new int[row][column]; //读取稀疏数组后几行数据,并赋给原始的二维数据 for (int i =1;i<sparseArr.length;i++) { origiArr[sparseArr[i][0]][sparseArr[i][1]] = sparseArr[i][2]; } //输出得到的原始数组 for (int[] rows : origiArr) { for (int data : rows) { System.out.printf("%d\t",data); } System.out.println(); } } }
队列
- 队列是一个有序列表,可以用数组或是链表来实现
- 遵循先进先出的原则
使用数组模拟队列:
- 若用数组的结构来存储队列,maxSize表示队列的最大容量
- 因为队列的输入输出分别从前后端来处理,因此需要两个变量front和rear分别记录队列前后端的下标,front会随着数据输出而改变,rear则会根据数据的输入而改变。
思路:
将数据存入队列时:
- 将尾指针往后移:rear+1,当front == rear[空队列]
- 当rear小于maxSize-1,则将数据存入rear所指的数组元素中,否则无法存入数据。rear == maxSize-1[队列满]
没有优化的代码
package com.joyce.queue; import java.util.Scanner; public class ArrayQueueTest { public static void main(String[] args) { ArrayQueue queue = 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': queue.showQueue(); break; case 'e': loop = false; break; case 'a': System.out.println("Please enter a value:"); int value = scanner.nextInt(); queue.addQueue(value); break; case 'g': try { int result = queue.getQueue(); System.out.printf("Get the value %d\n",result); } catch (Exception e) { System.out.println(e.getMessage()); } break; case 'h': try { int headValue = queue.headQueue(); System.out.printf("Get the head value:%d\n",headValue); } catch (Exception e) { System.out.println(e.getMessage()); } 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]; this.front = -1; this.rear = -1; } private boolean isFull() { return rear == maxSize-1; } private boolean isEmpty() { return rear == front; } //添加数据到队列 public void addQueue(int value) { if(isFull()) { System.out.println("Queue is full, cannot add data"); } rear++; arr[rear] = value; } //获取队列的数据,出队列 public int getQueue() { //判断队列时否为空 if(isEmpty()) { //抛出异常 throw new RuntimeException("The queue is empty"); } front++; return arr[front]; } //显示队列的所有数据 public void showQueue() { if(isEmpty()) { System.out.println("The queue is empty"); 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("The queue is empty"); } return arr[front+1]; } }
问题分析并优化:
- 目前数组使用一次就不能用,没有达到复用额效果
- 将这个数组使用算法,改进成一个环形的队列 取模:%
- front和rear初始化全部为0;
- rear为队列最后一个元素的下一个
- 当队列满的时候条件:(rear+1)%maxSize == front; //最后一个元素的下标为maxSize-1,所以当rear+1就为maxSize, 模一下如果刚好是第一个元素的位置,则队列为满的
- 当队列为空的条件:front == rear;
- 队列总是会空着一个,因为rear总是指向最后元素的下一个
package com.joyce.queue; import java.util.Scanner; public class ArrayQueueTest { public static void main(String[] args) { ArrayQueue queue = 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': queue.showQueue(); break; case 'e'://退出 scanner.close(); loop = false; break; case 'a': System.out.println("Please enter a value:"); int value = scanner.nextInt(); queue.addQueue(value); break; case 'g': try { int result = queue.getQueue(); System.out.printf("Get the value %d\n",result); } catch (Exception e) { System.out.println(e.getMessage()); } break; case 'h': try { int headValue = queue.headQueue(); System.out.printf("Get the head value:%d\n",headValue); } catch (Exception e) { System.out.println(e.getMessage()); } 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]; this.front = -1; this.rear = -1; } private boolean isFull() { return rear == maxSize-1; } private boolean isEmpty() { return rear == front; } //添加数据到队列 public void addQueue(int value) { if(isFull()) { System.out.println("Queue is full, cannot add data"); return;//不能加以后要记得返回 } rear++; arr[rear] = value; } //获取队列的数据,出队列 public int getQueue() { //判断队列时否为空 if(isEmpty()) { //抛出异常 throw new RuntimeException("The queue is empty"); } front++; return arr[front]; } //显示队列的所有数据 public void showQueue() { if(isEmpty()) { System.out.println("The queue is empty"); 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("The queue is empty"); } return arr[front+1]; } }
 
                    
                
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号