数组结构和算法--2环绕队列

环绕队列

队列含义:

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

数组模拟队列思路
队列本身是有序列表,使用数组的结构来存储队列的数据,maxSize是该队列的最大容量
因为队列的输出,输入是分别从前后端来处理,因此需要两个变量front及rear分别记录队列前后端的下标,
front会随着数据输出而改变,而rear则是随着数据输入而改变
数组模拟环形队列思路
1front变量的含义做调整,front就指向队列的第一个元素,也就是说arr[front] 就是队列的第一个元素,front的初始值=0
2rear变量的含义做调整,real指向队列的最后一个元素的后一个位置,因为希望空出一个空间做约定,rear的初始值=0
3当队列满时,条件是[rear+1]%maxSize==front
4当队列为空时条件rear==front
5队列中有效的数据个数[rear+maxSize-front]%maxSize

问题1:为什么拿到%maxSize的值

因为数组是一个环形数组,当数组末尾存满,但数组开头的数据取出时,可以把数据接着存到空位。所以用到%maxSize

front代表的就是数组第一个值,rear代表数组最后一个值,此时的环形数组的坐标不代表它属于开头还是结尾

问题2:空队列rear==front和满队列[rear+1]%maxSize==front条件的不同点:

按照如上图示,real==front会有两种情况,为空或为满。我们修改其条件,保留一个元素空间。也就是说,队列满时,数组中还有一个空闲单元。

如下图所示,我们就认为此队列已经满了,也就是说,我们不允许上图情况出现。

例子

package com.ujiuye.queue;

import java.util.Scanner;

public class CircleArrayQueue {
    public static void main(String[] args) {
        System.out.println("测试模型队列案例");
        //数组长度为3,但是其中有一个是空的,所以最多能放两个数据
        CircleArray queue = new CircleArray(3);
        Scanner sc = new Scanner(System.in);
        char key= ‘ ‘;
        boolean flag = true;
        while(flag) {
            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],查看列头数据");
            System.out.println("==================");
            System.out.println("请输入您要进行的操作(请用缩写字母或英文回复!)");
            key = sc.next().charAt(0);
            switch(key) {
            case ‘s‘:
                queue.showQueue();
                break;
            case ‘a‘:
                System.out.println("请添加一个数值");
                int n = sc.nextInt();
                queue.addQueue(n);
                break;
            case ‘g‘:
                try {
                    int res = queue.getQueue();
                    System.out.printf("取出的数值是%d\n",res);
                }catch(Exception e) {
                    System.out.println(e.getMessage());
                }
                break;
            case ‘h‘:
                try {
                    int res = queue.headQueue();
                    System.out.printf("队列头数值是%d\n",res);
                }catch(Exception e) {
                    System.out.println(e.getMessage());
                }
                break;
            case ‘e‘:
                sc.close();
                flag = false;
                break;
            default:
                break;
            }
        }

    }
}
class CircleArray{
    //表示数组的最大容量
    private int maxSize;
    //指向队列的第一个元素,arr[front] 就是队列的第一个元素,初始值为0
    private int front;
    //指向队列中的最后一个元素的后一个位置,因为希望空出一个空间做约定,rear的初始值=0
    private int rear;
    //用来存储数据,模拟队列
    private int[] arr;
    public CircleArray(int maxSize) {
        this.maxSize = maxSize;
        arr = new int[maxSize];
    }
    //当队列满时,条件是[rear+1]%maxSize==front
    public boolean isFull() {
        return (rear+1)%maxSize == front;
    }
    //当队列为空时条件rear==front
    public boolean isEmpty() {
        return rear == front;
    }
    //往队列里添加数据
    public void addQueue(int n) {
        //先判断队列是否满了
        if(isFull()) {
            System.out.println("队列已满,请排队");
            return;
        }
        //因为rear表示最后一个元素的后一个位置,肯定是空的,所以直接放进去即可不用加1
        arr[rear] = n;
        //将rear后移,考虑环绕问题,所以用取模 的方式
        rear = (rear+1)%maxSize;
    }
    //从队列中拿数据
    public int getQueue() {
        //先判断队列是否为空
        if(isEmpty()) {
            //抛异常不用return
            throw new RuntimeException("队列为空,暂无数值");
        }
        //取队列中的第一值
        int value=arr[front];
        //此时要把front后移,保证再次取值拿到的是第一个值,同时考虑环绕问题
        front = (front+1)%maxSize;
        return value;
    }
    //显示队列中的所有值
    public void showQueue() {
        //先判断队列是否为空
        if(isEmpty()) {
            throw new RuntimeException("队列为空,暂无数值");
        }
        //遍历要从第一个数值front开始遍历
        for(int i = front;i<size()+front;i++) {
            System.out.printf("arr[%d]=%d\n",i%maxSize,arr[i%maxSize]);
        }
    }
    //求出当前列表数据的个数
    public int size() {
        return (rear+maxSize-front)%maxSize;
    }
    //显示队列的头数据
    public int headQueue() {
        if(isEmpty()) {
            throw new RuntimeException("队列为空,暂无数值");
        }
        return arr[front];
    }
}

。。

原文地址:https://www.cnblogs.com/bai3535/p/12094059.html

时间: 2024-10-14 17:40:23

数组结构和算法--2环绕队列的相关文章

数组结构和算法-1稀疏数组

1稀疏数组 使用:当一个数组中大部分元素为0,或者为同一个值的数组时,可以使用稀疏数组来保存该数组 稀疏数组的处理方法: 1记录数组一共有几行几列,有多少个不同的值 2把具有不同值的元素的行列及值记录在一个小规模的数组中,从而缩小程序的规模 //拿五子棋为例,创建一个原始的二维数组11*11 //0表示没有棋子,1表示黑子,2表示白子 int[][] chessArr1 = new int[11][11]; chessArr1[1][2] = 1; chessArr1[2][3] = 2; ch

用数组结构实现大小固定的栈和队列

给定长度为size的数组,将其长度设置为大小为size的栈(队列),添加的数字如果超过了既定的长度就报错! 先实现栈(先进后出): 后实现队列(先进先出): 代码如下: 1 //例子:长度为6的数组,设置大小为6的栈,超过长度就会报错 2 //用数组结构实现大小固定的队列和栈 3 public class Bokeyuan { 4 //使用数组实现栈 5 public static class ArrayStack{ 6 private Integer[] arr;//数组 7 private

分别用数组和链表实现栈和队列

2015.2.8星期二,晴天 栈的数组操作: 栈的特点:先进后出,后进先出. 用数组的方式实现:首先需要创建一个结构体,在结构体里面包括数据指针.指向栈顶的”指针“和标记栈的大小的一个变量.数据指针是指向一定大小的数组的首地址.结构体和这个数组够成一个完整的栈. 1.在创建栈的操作中,主要就是创建这个结构体和这个数组,并对其进行一定的初始化,这个操作和链表的创建比较类似,初始化的语句:stack->max_depth = max_depth; //说明栈的大小stack->pop = -1;

数据结构与算法--栈、队列(队列)

Hello,everybody.我们又见面了.今天我们来学习一下队列这个数据结构,let's Go,开始我们的征程吧. 首先,举两个生活中的常见例子.相信大家,在用电脑工作娱乐时,都会碰到这样的现象.当我们点击程序或进行其他操作时,电脑处于死机状态.正当我们准备Reset时,它突然像打了鸡血似的,突然把刚才我们的操作,按顺序执行了一遍.之所以会出现这个现象,是因为操作系统的多个程序,需要通过一个管道输出,而按先后顺序排队造成的. 还有有个例子,在我们打客服热线时,有时会出现等待的现象.当其他客户

经典白话算法之优先级队列

<1>概念 优先级队列,顾名思义,就是一种根据一定优先级存储和取出数据的队列.它可以说是队列和排序的完美结合体,不仅可以存储数据,还可以将这些数据按照我们设定的规则进行排序.优先级队列是堆的一种常见应用.有最大优先级队列(最大堆)和最小优先级队列(最小堆).优先级队列是一种维护有一组元素构成的集合S的数据结构. <2>优先队列支持的基本运算 [cpp] view plaincopy //建立一个保存元素为int的优先级队列,其实是建了一个小顶堆 //但是请特别注意这样的建的堆默认是

毕业了-二叉树层次遍历算法-借助循环队列这个数据结构来实现,悟:数据结构是用来实现算法的

//代码进过测试,直接可以拿来用//关键就是那一点未透--队列.// 关键就是一个出队,一个入队操作.#include<iostream> #include<stdio.h> #include<stack> #include<queue> #include<malloc.h> # define MaxSize 100 using namespace std; //二叉树结点 typedef struct BTNode{ char data; st

数据结构 数组,链表,栈,队列理解

数据结构 数据结构是指相互之间存在一种或多种特定关系的数据元素的集合.再简单描述一下:数据结构就是描述对象间逻辑关系的学科. 数据存储结构 常用的数据存储方式有两种:顺序存储,非顺序存储.顺序存储就是把数据存储在一块联系的存储介质(硬盘或内存等)中.反之则是非顺序存储. Java中的数组就是典型的顺序存储,链表就是非顺序存储.数组存储数据时会开辟出一块联系内存,按顺序存储.链表先不会开辟出一块内存来,而是只需要知道下一个节点存储的位置,就能把所以的数据连起来了.所以单向链表的最后一个节点是指向N

数组集合删除算法

数组集合删除算法: 删除: /** * 更多资料欢迎浏览凯哥学堂官网:http://kaige123.com * @author 小沫 */ public void remove(int index){ //objs的长度如果小于0或对象值小于等于0那么抛出数组越界异常 if(objs.length<0||this.index.0){ throw new IndexOutOfBoundsException(); } if(this.index-1==index){ //当前对象的是所占长度-1等

数组集合添加算法

集合是无限存储的容器: 数组集合采用的算法是一开始先开辟好有限的空间进行存储放进来的数据. 等需要再次存放数据的时候,再去开辟一块比原来的空间多的容量之前,老的数据导入进新开辟的空间,然后再把新进来的数据放进空间里,依次这样进行开辟导入就形成了无限的容器.这就是数组集合的算法.  在java源码里面,采用的导入方式是直接调用本地系统语言来直接导入数据,这样提高了效率,一万毫秒才能完成的事情也许四千毫秒就执行完毕. 取消for循环导入使用System.arraycopy如下代码: /** * 更多