007 稀疏数组的应用场景

基本介绍:
当一个数组中大部分元素为0,或者为同一个数值的数组时,可以稀疏数组来保存该数组

稀疏数组的处理方法是:

  1. 记录数组一共有几行几列,有多少个不同的值
  2. 把具有不同值的元素的行列及值记录在一个小规模的数组中,从而缩小程序的规模

008 稀疏数组转换的思路分析

应用实例

  1. 使用稀疏数组,来保留类似前面的二维数组(棋盘、地图等等)
  2. 把稀疏数组存盘,并且可以重新恢复原来的二维数组数
  3. 整体思路分析

二维数据转稀疏数组的思路

  • 遍历原始的二维数组,得到有效数据的个数 sum
  • 根据 sum 就可以创建稀疏数组 sparseArr in[sum + 2] [3]
  • 将二维数组的有效数据存入到稀疏数组中
    稀疏数组转原始二维数组
  1. 读取稀疏数组的第一行,根据第一行,创建原始的二维数组,比如上面的 chessArr2 = ing[11][11]
  2. 在读取稀疏数组后几行的数据,并赋给原始的二维数组

009 稀疏数组的代码实现

package com.old.sparseArray;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;chessArr1[4][5] = 1;//输出原始的二维数据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++) {int[] ints = chessArr1[i];for (int j = 0; j < ints.length; j++) {if (ints[j] != 0) {sum++;}}}System.out.println("总数:" + sum);//2.创建对应的稀疏数组 sum + 1是因为数组是从0开始,所有需要加1int sparseArr[][] = new int[sum + 1][3];/*** 给稀疏数组赋值 这里为什么这样还未明白* 这里是为了记录原始数组的行和列的长度,而最后一个值是用于保存* 原始数组的有效值个数*/sparseArr[0][0] = 11;sparseArr[0][1] = 11;sparseArr[0][2] = sum;//遍历二维数组,将非0的值存放到稀疏数组中int count = 0;//用于记录是第几个非0数据for (int i = 0; i < chessArr1.length; i++) {int[] ints = chessArr1[i];for (int j = 0; j < ints.length; j++) {if (ints[j] != 0) {count++;sparseArr[count][0] = i;//记录原始数组的行sparseArr[count][1] = j;//记录原始数组的列sparseArr[count][2] = chessArr1[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]);}//将稀疏数组恢复成原始的二维数组//1.读取稀疏数组的第一行,int cheessArr2[][] = new int[sparseArr[0][0]][sparseArr[0][1]];//输出恢复后的二维数组System.out.println();//从稀疏数组的第二行开始for (int i = 1; i < sparseArr.length; i++) {int[] ints = sparseArr[i];for (int j = 0; j < ints.length; j++) {cheessArr2[ints[0]][ints[1]] = sparseArr[i][2];}}System.out.println("恢复后的原始数组");for (int[] row : cheessArr2) {for (int data : row) {System.out.printf("%d\t", data);}System.out.println();}}
}

010 队列的应用场景

队列介绍

  • 队列是一个有序列表,可以用数组或是链表实现
  • 遵循先入先出的原则。即:先存入队列的数据,要先取出。后存入的要后取出

010 数组模拟队列的思路分析

数组模拟队列

  • 队列本身是有序列表,若使用数组的结构来存储队列的数据,则队列数组的声明如下图,其中 maxSize 是该队列的最大容量
  • 因为队列的输出、输入是分别从前后端来处理,因此需要两个变量 front 及 rear 分别记录队列前后端的下标,front 会随着数据输出而改变,而 rear 则是随着数据输入而改变

011 数组模拟队列

  1. 将数据存入队列时称为 “addQueue” ,addQueue 的处理需要有两个步骤:
  2. 将尾指针往后移: rear + 1 , 当 front == rear 【空】
  3. 若尾指针 rear 小于队列的最大下标 maxSize - 1 ,则将数据存入 rear 所指的数组元素中,否则无法存入数据。 rear == maxSize -1 【队列满】

012 数组模拟队列代码实现

package com.old.queue;import java.util.Arrays;
import java.util.Scanner;public class ArrayQueueDemo {public static void main(String[] args) {/**队列是一种特殊的线性表,它只允许在表的前端进行删除操作,而在表的后端进行插入操作。一开始创建的头和尾的指针都是-1,当添加数据时,队列尾加1当输出数据时,队列头加1两个属性,front 和 rear 一个代表存到了哪,一个代表取到了哪,如果存和取是等于,代表队列中没有数据,如果 头 大于等于 队列的最大容量,就表示队列已经满了。数组是有顺序的,存入的第一个就在数组的 0 下标的位置,存入的第二个就在数组的 1 下标的位置,而加入数据一直对 队列尾属性+1,这样这个属性也代表着数组当前存入的数据的位置。取出数据则是对,队列头属性+1,这个属性就代表着当前数组取出数据的位置。因为队列只能一边存,一边取,所以存是从队列尾中加入,所以存入就队列尾加1,取出就是队列头加1*/ArrayQueue arrayQueue = new ArrayQueue(3);Scanner scanner = new Scanner(System.in);boolean loop = true;while (loop) {System.out.println("1.显示队列");System.out.println("2.退出程序");System.out.println("3.添加数据到队列");System.out.println("4.从队列取出数据");System.out.println("5.查看头数据");String s = scanner.nextLine();try {switch (s) {case "1":arrayQueue.showQueue();break;case "2":scanner.close();System.out.println("扫描器已关闭");loop = false;break;case "3":System.out.println("请输入数字:");String value = scanner.nextLine();arrayQueue.addQueue(Integer.valueOf(value));break;case "4":System.out.println("取出:" + arrayQueue.getQueue());break;case "5":System.out.println("取出:" + arrayQueue.headQueue());break;}} catch (Exception e) {System.out.println(e.getCause());}System.out.println();System.out.println("队列头,fron:" + arrayQueue.getFront());System.out.println("队列尾,rear:" + arrayQueue.getRear());System.out.println();}}
}//使用数组模拟队列
class ArrayQueue {private int maxSize;//数组最大容量/*** 队列头*/private int front;/*** 队列尾*/private int rear;private int[] arr;//该数组用于存放数据,模拟队列//创建队列的构造器public ArrayQueue(int arrMaxSize) {this.maxSize = arrMaxSize;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++;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];}public int getFront() {return front;}public int getRear() {return rear;}
}

问题分析并优化

  1. 目前数组使用一次就不能用,没有达到利用的效果
  2. 将这个数组使用算法,改进成一个环形的数组 取模:%

014 数组模拟环形队列的思路分析

对前面的数组模拟队列的优化,充分利用数组,因此将数组看做是一个环形的。(通过取模的方式来实现)
分析说明:

  1. 尾索引的下一个为头索引时表示队列满,即将队列容量空出一个作为约定,这个在做判断队列满的时候需要注意 (rear + 1 ) % maxSize == fron 满
  2. rear == front 空

015 数组模拟环形队列实现

将数组看做是一个环形。(通过取模的方式来实现)
分析说明:

  1. 尾索引的下一个为头索引时表示队列满,即将队列容量空出一个作为约定,这个在做判断队列满的时候需要注意 (rear + 1) % maxSize == front 即满
  2. rear == front 空
package com.old.queue;import java.util.Arrays;
import java.util.Scanner;/*** 环形数组队列*/
public class CircleArrayQueue {public static void main(String[] args) {CircleArray queue = new CircleArray(3);Scanner scanner = new Scanner(System.in);boolean loop = true;while (loop) {System.out.println("1.显示队列");System.out.println("2.退出程序");System.out.println("3.添加数据到队列");System.out.println("4.从队列取出数据");System.out.println("5.查看头数据");String s = scanner.nextLine();try {switch (s) {case "1":queue.showQueue();break;case "2":scanner.close();System.out.println("扫描器已关闭");loop = false;break;case "3":System.out.println("请输入数字:");String value = scanner.nextLine();queue.addQueue(Integer.valueOf(value));break;case "4":System.out.println("取出:" + queue.getQueue());break;case "5":System.out.println("取出:" + queue.headQueue());break;}} catch (Exception e) {System.out.println(e.getCause());}System.out.println();System.out.println("队列头,fron:" + queue.getFront());System.out.println("队列尾,rear:" + queue.getRear());System.out.println();}}
}//使用数组模拟队列
class CircleArray {private int maxSize;//数组最大容量/*** 队列头* front 变量的含义做一个调整:front 就指向队列的第一个元素,也就是说* arr[front] front 的初始值 = 0*/private int front;/*** 队列尾* front 变量的含义做一个调整: rear 指向队列的最后一个元素的后一个位置,* 因为希望突出一个* rear 的初始值 = 0*/private int rear;private int[] arr;//该数组用于存放数据,模拟队列//创建队列的构造器public CircleArray(int arrMaxSize) {this.maxSize = arrMaxSize;arr = new int[maxSize];front = 0;//队列头部,分析出,front 是指向队列头的前一个位置rear = 0;//指向队列尾,指向队列尾的数据(即就是队列最后一个数据)}//判断队列是否满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;}//因为 rear 本身就指向下一个元素,所以直接将数据加入arr[rear] = n;rear = (rear + 1) % maxSize;}//获取队列数据 出队列public int getQueue() {//判断队列是否为空if (isEmpty()) {throw new RuntimeException("队列中没有数据");}/*** front 本身就指向了队列的第一个元素* 1. 先把 front 对应的值保留到一个临时变量* 2. 将 front 后移,考虑取模. 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++) {int index = i % maxSize;System.out.printf("arr[%d]=%d\n", index, arr[index]);}}//求出当前队列有效数据的个数public int size() {return (rear + maxSize - front) % maxSize;}//显示队列的头数据,不是取出数据public int headQueue() {if (isEmpty()) {throw new RuntimeException("队列中没有数据");}return arr[front];}public int getFront() {return front;}public int getRear() {return rear;}
}

数组结构与算法-007-015稀疏数组与队列相关推荐

  1. 【自学笔记】尚硅谷数据结构与算法Chapter 2 稀疏数组和队列

    Chapter 2 稀疏数组和队列 文章目录 Chapter 2 稀疏数组和队列 2.1 稀疏数组 2.1.1 基本介绍 2.1.2 应用案例 2.2 队列 2.2.1 队列介绍 2.2.2 用数组模 ...

  2. Qz学算法-数据结构篇(稀疏数组、队列)

    目录 1.稀疏(sparse array)数组 需求引入 分析问题 2.队列(queue) 1.数组模拟队列 需求引入 1.1介绍 1.2数组模拟队列 1.3思路分析 1.4代码实现 2.数组模拟环形 ...

  3. JavaScript数组结构与算法——数组详解(中)

    迭代器方法 在上篇中,我们探讨了很多数组方法,接下来总结一下最后一组方法--迭代器方法.这些方法对数组的每个元素应用一个函数,可以返回一个值.一组值.或者一个新数组. 1.不生成新数组的迭代器方法 以 ...

  4. android 求数组最大值,面试算法知识梳理(7) - 数组第四部分

    面试算法代码知识梳理系列 一.概要 本文介绍了有关数组的算法第四部分的Java代码实现,所有代码均可通过 在线编译器 直接运行,算法目录: 求数组当中的最长递增子序列(求数组当中的最长递减子序列) 区 ...

  5. 数组结构与算法-036-042 前中后缀表达式-逆波兰计算器

    036 前缀 中缀 后缀(逆波兰表达式)表达式 前缀表达式 前缀表达式(波兰表达式) 前缀表达式又称波兰表达式,前缀表达式的运算符位于操作数之前 举例说明:(3 + 4) * 5 -6 对应的前缀表达 ...

  6. python遍历数组冒泡排序_Python算法(一) 数组冒泡排序(难度等级:easy)

    冒泡排序(Bubble Sort)是一种典型的交换排序算法,通过交换数据元素的位置进行排序. 算法原理:从无序序列头部开始,进行两两比较,根据大小交换位置,直到最后将最大(小)的数据元素交换到了无序队 ...

  7. 前端学习(3347):数组方法的运用和总结稀疏数组

  8. 尚硅谷数据结构和算法01-数据结构介绍和稀疏数组

    文章目录 一.数据结构组成 1.线性结构 2.非线性结构 二.稀疏数组 1.应用场景: 2.稀疏数组转换的思路分析 3.代码实现 补充: %d\t 一.数据结构组成 包括:线性结构和非线性结构 1.线 ...

  9. 数据结构与算法————稀疏数组

    引言 数据压缩方面,我们往往可以通过稀疏数组来保存有效数据,节省存储空间. 一.稀疏数组的概念 当一个数组中大部分元素是0,或为同一个值的时候,可以使用稀疏数组来保存数组. 它是一个十分有效的存储结构 ...

最新文章

  1. Linux手动启动、停止多个服务用的shell脚本
  2. php file_get_contents遇到https的处理办法
  3. Git常用命令速查表
  4. 成功解决numpy.linalg.LinAlgError: singular matrix
  5. [网络安全自学篇] 六十五.Vulnhub靶机渗透之环境搭建及JIS-CTF入门和蚁剑提权示例(一)
  6. 牛客假日团队赛5J 护城河 bzoj 1670: [Usaco2006 Oct]Building the Moat护城河的挖掘 (凸包的周长)...
  7. Firewall配置
  8. 自己写了一个多行文本溢出文字补全的小库, 说不定你会用得到的
  9. 总结PLSQL的快捷键以及使用技巧
  10. 第十五篇 Python之文件处理
  11. Leetcode 114.二叉树展开为链表
  12. Linux使用openssl实现RSA非对称加密
  13. 文件系统03 - 零基础入门学习Delphi36
  14. 求整数数组的最小值c语言,编程实现求一个整数数组num[]中的最大值与最小值并输出结果的程序...
  15. 手把手教你快速构建自定义分类器
  16. 【如见】MMD动作+镜头数据下载
  17. Glide库里,藏了一套你心心念念的GIF压缩工具集
  18. 键盘拆开重新安装步骤_笔记本键盘怎么拆——键盘分拆详细步骤
  19. 怎么开启2345加速浏览器的过滤弹窗广告
  20. 修改NPM的默认安装路径

热门文章

  1. 点击按钮没有反应,onclick函数点击无反应的原因
  2. 阿里“中供系”前世今生:马云麾下最神秘的子弟兵
  3. 高标准农田在线监测系统解决方案
  4. 老司机的奇怪noip模拟T1-guanyu
  5. python自带的函数有哪些_内置函数 python自带的函数
  6. An Empirical Evaluation of Generic Convolutional and Recurrent Networks for Sequence Modeling
  7. BSGS(拔山盖世算法),北上广深算法
  8. MIT Technology Review 2022年“全球十大突破性技术”解读
  9. JavaScript弹出模式窗口
  10. js 年会大屏_ECharts + Jquery 做大屏展示