Scala数据结构和算法:队列、队列使用场景、数组模拟队列、数组模拟环形队列、队列图解

队列的一个使用场景

银行排队的案例:
在这里插入图片描述

队列介绍

队列是一个有序列表,可以用数组或是链表来实现。
遵循先入先出的原则。即:先存入队列的数据,要先取出。后存入的要后取出
示意图:(使用数组模拟队列示意图)
在这里插入图片描述

数组模拟队列

队列本身是有序列表,若使用数组的结构来存储队列的数据,则队列数组的声明如下图, 其中 maxSize 是该队列的最大容量。

因为队列的输出、输入是分别从前后端来处理,因此需要两个变量 front及 rear分别记录队列前后端的下标,front 会随着数据输出而改变,而 rear则是随着数据输入而改变,如图所示:
在这里插入图片描述

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

代码实现
问题分析并优化

class ArrayQueue(arrMaxSize: Int) { val maxSize: Int = arrMaxSize
  val array = new Array[Int](arrMaxSize)
  var front: Int = -1
  var rear: Int = -1
}
 //初始化
 val queue = new ArrayQueue(3)

rear 是队列最后[含]
front 是队列最前元素[不含]

数组模拟队列

出队列操作getQueue
显示队列的情况showQueue
查看队列头元素headQueue
退出系统exit

将原来的队列的查看队列头元素的代码写完.

数组模拟环形队列

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

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

(cq.rear + cq.maxSize – cq.front) % cq.maxSize

class CircleQueue {
  private int maxSize;
  private int[] arr; // 该数组存放数据,模拟队列
  private int front; // 指向队列头部
  private int rear; // 指向队列的尾部
  public CircleArrayQueue(int arrMaxSize) {
  	maxSize = arrMaxSize;
	arr = new int[maxSize];
   } 
  public boolean isFull()  {
    //尾索引的下一个为头索引时表示队列满,即将队列容量空出一个作为约定(!!!)
    return (rear + 1) % maxSize == front; }
  public boolean isEmpty()  {
    this.tail == this.head }

   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 int size()  {
    return (rear + maxSize - front) % maxSize;}}

小结

队列是有序列表
front 初始化为-1, 表示队列的头,但是约定不包含头元素, 即指向队列的第一个元素的前一个位置.
rear 初始化-1, 指向队列尾部,包含最后这个元素
判断队列空,front == rear 表示空
判断队列满, rear == maxSize -1

队列图解

在这里插入图片描述

队列代码

package datastructure

import scala.io.StdIn

/**
  * 环形队列
  * 如果不使用环形队列,则从队列中取出元素时不会释放队列的使用空间
  * @author cherry
  * @create 2019-09-17-22:45
  */
class CircleArrayQueueDemo(arrMaxSize: Int) {
  val maxSize = arrMaxSize // 指定队列的大小
  val arr = new Array[Int](maxSize) // 队列中数据,存放在数组,即数组模拟队列
  //front 初始化为0, 表示队列的头,指向队列的第一个元素
  var front = 0
  //rear 初始化0, 指向队列最后这个元素的后一个位置
  var rear = 0

  //判断队列空
  def isEmpty(): Boolean = rear == front

  //判断满
  def isFull(): Boolean = (rear + 1) % maxSize == front

  //添加数据到队列
  def addQueue(num: Int): Unit = {
    if (isFull()) {
      println("队列满,不能加入")
      return
    }
    arr(rear) = num
    //将rear 后移
    rear = (rear + 1) % maxSize
  }

  //从队列中取出数据, 可能取得数据,可能取不到数据(异常)
  def getQueue(): Any = {
    if (isEmpty()) return new Exception("队列空,没有数据")
    //因为front指向队列的第一个元素
    val res = arr(front) //先将保存到临时变量
    front = (front + 1) % maxSize // front后移
    res //返回临时变量
  }

  //遍历显示队列, 动脑筋
  //思路
  // 1. 从front 开始打印,打印多少个元素
  // 2. 所以,需要统计出该队列有多少个有效元素
  def show(): Unit = {
    if (isEmpty()) {
      println("队列空")
      return
    }
    //这里使用%方式解决
    for (i <- front until front + size()) {
      printf("arr(%d)=%d \t", i % maxSize, arr(i % maxSize))
    }
  }

  //编写一个方法,统计当前有多少个元素
  def size(): Int = (rear + maxSize - front) % maxSize

  //查看队列的头元素,但是不取出
  def peek(): Any = {
    if (isEmpty()) return new Exception("队列空,无数据")
    arr(front) //front 不要动
  }


}

object CircleArrayQueueDemo {
  def main(args: Array[String]): Unit = {
    //测试一把
    val queue = new CircleArrayQueueDemo(4)
    //菜单演示
    var key = ""

    while (true) {
      print("请选择菜单:show: 显示队列;add : 添加数据;get : 获取数据;peek : 取出数据;exit: 退出程序:")
      println()
      key = StdIn.readLine()
      key match {
        case "show" => queue.show()
        case "add" =>
          println("请输入一个数")
          val num = StdIn.readInt()
          queue.addQueue(num)
        case "get" =>
          //对取回的值,进行判断
          val res = queue.getQueue()
          //如果是异常
          if (res.isInstanceOf[Exception]) {
            println(res.asInstanceOf[Exception].getMessage)
          } else {
            //Int
            printf("队列取出的值=%d", res)
          }
        case "peek" =>
          //查看头元素值,进行判断
          val res = queue.peek()
          //如果是异常
          if (res.isInstanceOf[Exception]) {
            println(res.asInstanceOf[Exception].getMessage)
          } else {
            //Int
            printf("队列当前头元素=%d", res)
          }

      }
    }
  }
}

测试代码
在这里插入图片描述
发现从数组队列中取出元素后还能再插入元素

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值