• 队列


    队列的一个使用场景

    银行排队的案例:

     

    队列介绍

    1. 队列是一个有序列表,可以用数组或是链表来实现。
    2. 遵循先入先出的原则。即:先存入队列的数据,要先取出。后存入的要后取出
    3. 示意图:(使用数组模拟队列示意图)

    数组模拟队列

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

      说明

      代码实现

      package com.atguigu.chapter18

      import scala.io.StdIn

      object ArrayQueueDemo {

      def main(args: Array[String]): Unit = {

      //初始化一个队列

      val queue = new ArrayQueue(3)

      var key = ""

      while (true) {

      println("show: 表示显示队列")

      println("exit: 表示退出程序")

      println("add: 表示添加队列数据")

      println("get: 表示取出队列数据")

      println("head: 查看队列头的数据(不改变队列)")

      key = StdIn.readLine()

      key match {

      case "show" => queue.showQueue()

      case "add" => {

      println("请输入一个数")

      val value = StdIn.readInt()

      queue.addQueue(value)

      }

      case "get" => {

      val res = queue.getQueue()

      if (res.isInstanceOf[Exception]) {

      println(res.asInstanceOf[Exception].getMessage)

      } else {

      println(s"取出数据是 $res")

      }

      }

      case "head" => {

      val res = queue.headQueue()

      if(res.isInstanceOf[Exception]) {

      //显示错误信息

      println(res.asInstanceOf[Exception].getMessage)

      }else {

      println("队列头元素值为=" + res)

      }

      }

      case "exit" => System.exit(0)

      }

      }

      }

      }

      //使用数组模拟队列

      //队列存在的问题是,数据空间不能复用

      class ArrayQueue(arrMaxSize: Int) {

      val maxSize = arrMaxSize

      val arr = new Array[Int](maxSize) //该数组存放数据,模拟队列

      var front = -1 // 指向队列头部, 分析出front 是指向队列数据的前一个位置

      var rear = -1 // 指向队列的尾部,分析出rear 是指向队列的最后数据()

      //判断队列是否满

      def isFull(): Boolean = {

      rear == maxSize - 1

      }

      //判断队列是否空

      def isEmpty(): Boolean = {

      front == rear

      }

      //添加数据到队列

      def addQueue(n: Int): Unit = {

      //判断是否满

      if (isFull()) {

      println("队列满,无法加入..")

      return

      }

      rear += 1 //先让rear 后移

      arr(rear) = n

      }

      def getQueue(): Any = {

      if (isEmpty()) {

      return new Exception("队列空~")

      }

      front += 1

      return arr(front)

      }

      //显示队列的所有数据

      def showQueue(): Unit = {

      if (isEmpty()) {

      println("队列空的,没有数据..")

      return

      }

      for (i <- front + 1 to rear) {

      printf("arr[%d]=%d ", i, arr(i))

      }

      }

      //查看队列的头元素,但是不是改变队列

      def headQueue(): Any = {

      if (isEmpty()) {

      return new Exception("队列空~")

      }

      //这里注意,不要去改变fornt

      return arr(front + 1)

      }

      }

      对上面代码的说明: 虽然实现了队列,但是数据空间不能复用,因此我们需要对其进行优化,使用取模的方式实现环形队列.

    数组模拟环形队列

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

      因为数组也可以通过取模的方式当做一个环形结构来使用,那么也可以解决约瑟夫问题.(提示,可以通过修改元素的值,来标志该元素对应的小孩是否出圈)

    • 分析说明:
    1. 尾索引的下一个为头索引时表示队列满,即将队列容量空出一个作为约定,这个在做判断队列满的
      时候需要注意 (rear + 1) % maxSize == front ]
    2. rear == front []
    3. 代码实现

      package com.atguigu.chapter18

      import scala.io.StdIn

      object CircleArrayQueueDemo {

      def main(args: Array[String]): Unit = {

      println("~~~环形队列的案例~~~")

      //初始化一个队列

      val queue = new CircleArrayQueue(4)

      var key = ""

      while (true) {

      println("show: 表示显示队列")

      println("exit: 表示退出程序")

      println("add: 表示添加队列数据")

      println("get: 表示取出队列数据")

      println("head: 查看队列头的数据(不改变队列)")

      key = StdIn.readLine()

      key match {

      case "show" => queue.showQueue()

      case "add" => {

      println("请输入一个数")

      val value = StdIn.readInt()

      queue.addQueue(value)

      }

      case "get" => {

      val res = queue.getQueue()

      if (res.isInstanceOf[Exception]) {

      println(res.asInstanceOf[Exception].getMessage)

      } else {

      println(s"取出数据是 $res")

      }

      }

      case "head" => {

      val res = queue.headQueue()

      if(res.isInstanceOf[Exception]) {

      //显示错误信息

      println(res.asInstanceOf[Exception].getMessage)

      }else {

      println("队列头元素值为=" + res)

      }

      }

      case "exit" => System.exit(0)

      }

      }

      }

      }

      //环形的队列和前面的单向队列有类似的地方,因为我们修改即可

      class CircleArrayQueue(arrMaxSize: Int) {

      val maxSize = arrMaxSize

      val arr = new Array[Int](maxSize) //该数组存放数据,模拟队列

      var front = 0 // 指向队列头部

      var rear = 0 // 指向队列的尾部

      //判断队列满的方法

      //队列容量空出一个作为约定

      def isFull(): Boolean = {

      //1 => rear 1

      //2 => rear 2

      //3 => rear 3

      (rear + 1) % maxSize == front

      }

      //判断队列空的条件

      def isEmpty(): Boolean = {

      rear == front

      }

      //添加数据到队列

      def addQueue(n: Int): Unit = {

      //判断是否满

      if (isFull()) {

      println("队列满,无法加入..")

      return

      }

      //将数据加入

      arr(rear) = n

      //然后将rear 后移, 这里必须考虑取模

      rear = (rear + 1) % maxSize

      }

      //取出队列的数据(按先进先出的原则)

      def getQueue(): Any = {

      if (isEmpty()) {

      return new Exception("队列空~")

      }

      //这里我们需要分析处理 front 已经指向了队列的头元素

      //1. 先把front 对应的数据保存到变量

      //2. front后移

      //3. 返回前面保存的变量值

      val value = arr(front)

      front = (front + 1) % maxSize

      return value

      }

      //显示队列的所有数据

      def showQueue(): Unit = {

      if (isEmpty()) {

      println("队列空的,没有数据..")

      return

      }

      //思路: front 取,取出几个元素

      //动脑筋

      for (i <- front until front + size()) {

      printf("arr[%d]=%d ", i % maxSize, arr(i % maxSize))

      }

      }

      //求出当前环形队列有几个元素

      //动脑筋

      //基础【问题/需求 ---> 设计算法】

      def size(): Int = {

      //rear = 1

      //front = 0

      //maxSize = 3

      (rear + maxSize - front) % maxSize //求出当前队列实际有多少个数据

      }

      //查看队列的头元素,但是不是改变队列

      def headQueue(): Any = {

      if (isEmpty()) {

      return new Exception("队列空~")

      }

      //这里注意,不要去改变fornt

      return arr(front)

      }

      }

    课堂练习:

    1. 同学们完成环形数组模拟的队列的输出

      (cq.tail + cq.maxSize - cq.head) % cq.maxSize

  • 相关阅读:
    UVa 11389
    uva 1418
    uva 10905 Children's Game
    uva 471
    UVA 1508
    Uva120 Stacks of Flapjacks
    UVA 10020 Minimal coverage
    UVA434
    UVa 311
    决策树算法
  • 原文地址:https://www.cnblogs.com/shuzhiwei/p/11210119.html
Copyright © 2020-2023  润新知