数据结构——队列(Java)

发布于:2025-09-07 ⋅ 阅读:(16) ⋅ 点赞:(0)

一.基本概念

队列用来存储逻辑关系为“一对一”的数据,是一种“特殊”的线性存储结构。

特点:

•先进先出:队列中元素的添加(入队enqueue)和移除(出队dequeue)遵循先进先出的原
则。
•端点:队列有两个主要的端点——队头(front)和队尾(rear)。队头是队列中最先入队
的元素所在的位置,而队尾则是最后入队的元素所在的位置。

强调:队列不要混淆,栈是一端开口、另一端封口,元素入栈和出栈遵循“先进后出”原则;队列是两端都开口,但元素只能从一端进,从另一端出,且进出队列遵循“先进先出”的原则。

        实现方法:

        1.顺序表实现

        2.链表实现

以链表的方式为例子

二.链表实现队列

        队列的API设计

队列初始化

       

class Queue <T>
{
   //结点类
    class Node
    {
        public T data;//存储数据
        public Node next;//下一个结点
      public Node(T data , Node next)
      {
          this.data = data;
          this.next = next;
      }
    }
    //创建首结点
    private Node head;
    //尾结点
    private Node last;
    //队列个数
    private int N;
    public Queue()
    {
        this.head =new Node(null,null);
        this.last =null;
        this.N =0;
    }

判断队列是否为空

思路分析:用布尔类型,直接返回数量

 //判断队列是否为空
    public boolean isEmpty()
    {
        return N == 0;
    }

获取队列个数

思路分析:直接返回数量

//返回队列元素个数
    public int size()
    {
        return N;
    }

插入元素

思路分析:

1.如果队列为空,将头结点指向新结点

2.创建变量1代替原先尾结点的数据

3.创建一个变量2当尾结点

4.将变量1的next引用指向变量2的值

 //插入元素
    public void enqueue(T data)
    {
        //保存当前的尾结点
        Node oldLast = last;
        //创建新结点为新的尾结点
        last = new Node(data, null);
        //判断队列是否为空
        if(isEmpty())
        {
            head.next = last;
        }
        else
        {
            //将原先尾结点的next指向新结点
            oldLast.next = last;
        }
        N++;
    }

元素取出

思路分析:根据先进先出原则,我们需要更新头结点的next所指向的值

 //从队列拿出一个元素
    public T dequeue()
    {
        //为空,返回null
        if(isEmpty())
        {
            return null;
        }
        //保存当前首结点
        Node oldFirst = head.next;
        //将首结点更新到下一个结点
        head.next = oldFirst.next;
        N--;
        //如果队列被删除完了,重置Last为null
        if(isEmpty())
        {
            last = null;
        }
        return oldFirst.data;//返回取出元素
    }

三.用栈来实现队列

思路分析:

栈是后进先出(LIFO)的数据结构,队列是先进先出(FIFO)的数据结构。我们可以使用两个栈,一个用于入队操作(记为 inStack ),一个用于出队等操作(记为 outStack )。 

当执行 push 操作时,直接将元素压入 inStack 。因为 inStack 只负责接收新元素,就像队列的尾部接收新元素一样。 

当执行 pop 和 peek 操作时,需要先判断 outStack 是否为空。如果 outStack 为空,就将 inStack 中的所有元素依次弹出并压入 outStack ,此时 outStack 栈顶元素就是队列的开头元素(因为 inStack 中先进入的元素会在转移到 outStack 后处于栈顶)。然后再执行相应的 pop 或 peek 操作。 

执行 empty 操作时,只需判断 inStack 和 outStack 是否都为空。  

完整代码

import java.util.Stack;



class MyQueue {
    private Stack<Integer> inStack; // 用于入队操作的栈
    private Stack<Integer> outStack; // 用于出队等操作的栈

    public MyQueue() {
        inStack = new Stack<>(); // 初始化入队栈
        outStack = new Stack<>(); // 初始化出队栈
    }

    public void push(int x) {
        inStack.push(x); // 将元素x压入入队栈,模拟队列的入队操作
    }

    public int pop() {
        if (outStack.isEmpty()) { // 如果出队栈为空
            while (!inStack.isEmpty()) { // 当入队栈不为空时
                outStack.push(inStack.pop()); // 将入队栈的元素依次弹出并压入出队栈
            }
        }
        return outStack.pop(); // 弹出并返回出队栈的栈顶元素,即队列开头的元素
    }

    public int peek() {
        if (outStack.isEmpty()) { // 如果出队栈为空
            while (!inStack.isEmpty()) { // 当入队栈不为空时
                outStack.push(inStack.pop()); // 将入队栈的元素依次弹出并压入出队栈
            }
        }
        return outStack.peek(); // 返回出队栈的栈顶元素,即队列开头的元素(不弹出)
    }

    public boolean empty() {
        return inStack.isEmpty() && outStack.isEmpty(); // 判断入队栈和出队栈是否都为空,都为空则队列空
    }
}
public class StudentMS4
{
    public static void main(String[] args)
    {
        MyQueue myQueue = new MyQueue();
        //调用push
        myQueue.push(1);
        myQueue.push(2);
        //调用peek
        System.out.println("队列开头的元素是:"+myQueue.peek());
        //调用pop
        System.out.println("移除并返回队列开头的元素:"+myQueue.pop());
        //调用empty方法
        System.out.println("队列是否为空:"+myQueue.empty());

    }
}

目录

一.基本概念

特点:

        实现方法:

二.链表实现队列

        队列的API设计

队列初始化

判断队列是否为空

获取队列个数

插入元素

元素取出

三.用栈来实现队列

思路分析:

完整代码



网站公告

今日签到

点亮在社区的每一天
去签到