小白学习数据结构-队列【超详细!】

目录

学习资料:b站韩顺平数据结构,参考笔记数据结构与算法 系列教程(笔记)仅自我学习总结记录用。

一、队列:

二、数组模拟队列

1、声明四个变量:

2、声明的方法:

3、各部分代码:

1)构造器:

2)判断是否为空

3)判断是否为满

4)入队列

5)出队列

6)显示队列中的数据

7)显示头部数据

8)显示尾部数据

总体代码:

三、环形队列

1、声明四个变量:

2、声明的方法:

3、各部分代码:

 1)构造器:【传入的是有效元素个数,数组的长度是有效元素个数+1】

2)判断是否为空【front==rear】

3)判断是否为满【(rear+1)%maxSize == front】

4)入队列【先存入值,再后移rear(后移要注意越界问题,取模)】

5)出队列【先取出值,再后移front,(后移要注意越界问题,取模)】

6)显示队列中的数据【从队首遍历,遍历次数为有效元素个数次,但索引越界了需要取模】

7)显示头部数据【最简单,队首数据】

8)显示尾部数据【取数据rear-1,但是可能rear为0,所以要条件表达式判断,为0队尾数据则为maxSize-1,最后一个数据】

总体代码:jie


学习资料:b站韩顺平数据结构,参考笔记数据结构与算法 系列教程(笔记)仅自我学习总结记录用。

一、队列:

队列是一个有序列表,可以用 数组 或链表实现。

特点:先入先出。

二、数组模拟队列

1、声明四个变量:

arr:用来存储数据的数组。

maxSize:该队列的最大容量。

front:队列头,指向队列头的前一个位置。

rear:队列尾,指向队列尾的最后一个有效数据元素。

2、声明的方法:

(构造器)

判断是否满 —— rear = maxSize - 1 (满)

判断是否空 —— rear = front (空)

入队列 —— 判断是否满,未满,rear后移,入队列

出队列 —— 判断是否空,未空,出队列,front后移

显示队列数据 —— 判断是否空

显示头部数据 —— 判断是否空

显示尾部数据 —— 判断是否空

3、各部分代码:
1)构造器:

2)判断是否为空

3)判断是否为满

4)入队列

5)出队列

6)显示队列中的数据

7)显示头部数据

8)显示尾部数据

总体代码:
package com.guigu.Queue;
//队列 特点:先入先出,先存入的数据先取出。
//数组模拟队列。
//arr 存储数据的数组
//front 队首,队列头部
//rear 队尾,队列尾部
//maxSize 队列的最大容量

//思路分析: add 向队列中添加数据
// 将尾指针往后移 ————> 判断队列是否为空(front == rear) :rear + 1
// 存入数据 ————> 判断队列是否满(rear < maxSize - 1): 未满则将数据存入rear所指的数组元素中,否则无法存入数据。
//
public class ArrayQueueDemo {
    public static void main(String[] args) {
        ArrayQueue queue = new ArrayQueue(3);
        //测试:入队列
        queue.add(1);
        queue.add(2);
        queue.add(3);
        System.out.println("1、测试:查看队列中的数据");
        queue.show();
        System.out.println("2、测试:查看队列头数据:" + queue.head());
        System.out.println("3、测试:查看队列尾数据:" + queue.tail());
        //测试添加数据
        queue.add(4);
        System.out.println("4、测试:(出队列)获取队列数据:" + queue.get());
        System.out.println("5、测试:查看队列中的数据");
        queue.show();
    }
}

class ArrayQueue{
    private int maxSize;//队列的最大容量,数组的索引范围是[0,maxSize - 1]。
    private int front;//队列头,指向队列头的前一个位置
    private int rear;//队列尾,指向队列尾的最后一个有效数据元素
    private int arr[];//用于存储数据,模拟队列
//构造器
    public ArrayQueue(int arrMaxSize){//数组最大的值
        maxSize = arrMaxSize;
        arr = new int[maxSize];
        front = -1;
        rear = -1;
    }
//判断队列是否为空,判断队尾是否等于队首,是则为空
    public boolean isEmpty(){
        return rear == front;
    }
//判断队列是否为满,rear = maxSize - 1,数组被完全使用,无法再存储更多数据。
    public boolean isFull(){
        return rear == maxSize - 1;
    }
//出队列,先判断是否为空,空则抛出异常。先进先出,front后移。
    public int get(){
        if(isEmpty()){
            throw new RuntimeException("队列空");
        }
        return arr[++front];
    }
//入队列,先判断是否为满,满则退出。入队列rear后移再赋值。
    public void add(int n){
        if(isFull()){
            System.out.println("队列已满");
            return;
        }
        rear++;
        arr[rear] = n;
    }
//展示队列中的数据————遍历数组。判断队列是否为空,空无法展示
    public void show(){
        if(isEmpty()){
            System.out.println("队列为空");
            return;
        }
        for (int i = 0; i <arr.length; i++){
            System.out.printf("arr[%d] = %d \n",i,arr[i]);
        }
    }
//查看队列的头部数据。front指向队列头前一个元素
    public int head(){
        if(isEmpty()){
            throw new RuntimeException("队列空");
        }
        return arr[front+1];
    }
//查看队列尾数据
    public int tail(){
        if(isEmpty()){
            throw new RuntimeException("队列空");
        }
        return arr[rear];
    }
}

结果:

 

三、环形队列

上面的普通数列,是一次性的,不可以复用。

环形数组需要注意!!!!!

rear和front的定义,队首队尾的概念

有效元素个数的计算

越界问题(左:rear-1可能是-1,右:rear或front+1可能超过了数组的maxSize)

遍历时,从队首开始,遍历有效元素个数次。注意越界问题。

1、声明四个变量:

arr:用来存储数据的数组。

maxSize:该队列的最大容量。

front:队列头,指向队列头。

rear:队列尾,指向队列尾有效数据元素的下一个位置。【rear的指向一直是空的】

2、声明的方法:

(构造器)

判断是否满 —— (rear + 1) % maxSize = front (满)

判断是否空 —— rear = front (空)

有效元素个数,公式:(rear - front +maxSize) % maxSize

入队列 —— 判断是否满,未满,入队列,rear后移【注意越界问题,取模】

出队列 —— 判断是否空,未空,出队列,front后移【注意越界问题,取模】

显示队列数据 —— 判断是否空

显示头部数据 —— 判断是否空

显示尾部数据 —— 判断是否空【注意尾部】

解释1:有效个数 (rear + maxSize - front) % maxSize

解释2:为什么rear一直指向空位置。

解释3:取模。

取模运算是为了处理环形队列的跨越边界问题

3、各部分代码:
 1)构造器:【传入的是有效元素个数,数组的长度是有效元素个数+1】

传入是有效数据个数。

2)判断是否为空【front==rear】

3)判断是否为满【(rear+1)%maxSize == front】

4)入队列【先存入值,再后移rear(后移要注意越界问题,取模)】

5)出队列【先取出值,再后移front,(后移要注意越界问题,取模)】

6)显示队列中的数据【从队首遍历,遍历次数为有效元素个数次,但索引越界了需要取模】

7)显示头部数据【最简单,队首数据】

8)显示尾部数据【取数据rear-1,但是可能rear为0,所以要条件表达式判断,为0队尾数据则为maxSize-1,最后一个数据】

总体代码:jie
package com.guigu.Queue;

//环形队列
//数组模拟队列的基础版,当填满队列之后就添加不进去了,获取数据也不能清空原队列中的数据。
//优化: 将数组改进成一个环形队列。
//front : 队列的第一个元素。(有所区别)。初始值为0
//rear : 队列的最后一个元素的下一个位置。(有所区别)。初始值为0
//队列满 : (rear + 1) % maxSize == front
//队列空 : rear == front
//队列中有效元素个数计算公式 : (rear + maxSize - front) % maxSize

public class CircleQueueDemo {
    public static void main(String[] args) {
        CircleQueue queue1 = new CircleQueue(3);//传入有效数据,3个,实际数组长度0-3(4)
        //测试:入队列
        queue1.add(1);
        queue1.add(2);
        queue1.add(3);
        System.out.println("1、测试:查看队列中的数据");
        queue1.show();
        System.out.println("2、测试:查看队列头数据:" + queue1.head());
        System.out.println("3、测试:查看队列尾数据:" + queue1.tail());
        //测试添加数据
        //queue1.add(4);
        System.out.println("4、测试:(出队列)获取队列数据:" + queue1.get());
        System.out.println("4、测试:(出队列)获取队列数据:" + queue1.get());
        queue1.show();
        queue1.add(4);
        System.out.println("5、测试:查看队列中的数据");
        queue1.show();
    }


}

class CircleQueue{
    private int maxSize;//队列最大容量
    private int front;//队列头,队头的元素
    private int rear;//队列尾,队尾的下一个元素,rear指向的位置一直是空的。
    private int arr[];//用于存储数据,模拟队列

    public CircleQueue(int arrMaxSize){
        maxSize = arrMaxSize + 1;//arrMaxSize有效数据个数,maxSize是数组长度。
        arr = new int[maxSize];
        front = 0;
        rear = 0;
    }
//判断队列是否满,
//front是队头元素的位置,rear是指向有效元素的下一个位置,如果rear不是指向一个空元素,那么无法区分 队列满和队列空
    public boolean isFull(){
        return (rear + 1) % maxSize == front;//用取模实现循环
    }
//判断队列是否空,
    public boolean isEmpty(){
        return front == rear;
    }
//有效个数,有效元素的数量是从 front 到 rear 的距离。
    public int size(){
        return (rear + maxSize - front) % maxSize;
    }
//入队列,先判断是否为满,满则退出。入队列rear赋值再后移(后移注意越界问题!)。
    public void add(int n){
        if(isFull()){
            System.out.println("队列已满");
            return;
        }
        //arr[rear++] = n;错误,可能越界
        arr[rear] = n;
        rear = (rear + 1) % maxSize;
    }
//出队列,先判断是否为空,空则抛出异常。先进先出,先出再front后移(后移注意越界问题)。
    public int get(){
        if(isEmpty()){
            throw new RuntimeException("队列空");
        }
        int value = arr[front];
        front = (front + 1) % maxSize;
        return value;
    }
//展示队列中的数据————遍历数组。
// 需要从队首开始打印,
// 打印的次数尾有效元素个数,
// 获取数据的下标,由于是环形的,需要使用取模的方式来获取
    public void show(){
        if(isEmpty()){
            System.out.println("队列为空");
            return;
        }
        for (int i = front; i < front + size(); i++){
            //size() 是有效元素的个数,而不是绝对数组下标的范围;
            //i 是逻辑上的数组下标,它应该以 i < front + size() 为条件。
            int index = i % maxSize;
            //遍历时需要用 i % maxSize 取模来确保数组下标始终在有效范围 [0, maxSize - 1] 内;
            System.out.printf("arr[%d] = %d \n",index,arr[index]);
        }
    }
//查看队列的头部数据。front指向队列头
    public int head(){
        if(isEmpty()){
            throw new RuntimeException("队列空");
        }
        return arr[front];
    }
//查看队列尾数据
    public int tail(){
        if(isEmpty()){
            throw new RuntimeException("队列空");
        }
        //错误:return arr[rear - 1];//当环形时,rear = 0
        return rear - 1 < 0 ? arr[maxSize - 1] : arr [rear - 1];
    }
}


结果:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值