Java数据结构(九):栈和队列

🌸雨落在了我的手上:个人主页

🐟个人仓库:Gitee仓库

❄️个人专栏:<<JaveSe>> <<C语言>> <<C语言数据结构>>**

🔥🔥🔥 人生格言:无人扶我青云志,我自踏雪至山巅

🎬 博主简介:


目录

一:栈(Stack)

1.概念

2.栈的使用

3.栈的模拟实现

二:队列(Queue)

1.概念

2.队列的使⽤

3.队列模拟实现

三:双端队列(Deque)

1.双端队列的使用


内容大纲:

本文介绍了三种常见的数据结构:栈、队列和双端队列。栈遵循后进先出(LIFO)原则,使用标准库Stack类演示了入栈、出栈等操作,并基于顺序表实现了自定义栈。队列遵循先进先出(FIFO)原则,通过LinkedList实现的Queue接口展示了队列操作,并基于单链表实现了自定义队列。双端队列(Deque)支持两端操作,通过ArrayDeque类演示了头尾插入、删除等特性。每种数据结构都包含概念讲解、标准库使用示例和模拟实现代码,帮助理解其底层原理和应用场景。


一:栈(Stack)

1.概念

栈:⼀种特殊的线性表,其只允许在固定的⼀端进⾏插⼊和删除元素操作。进⾏数据插⼊和删除操作 的⼀端称为栈顶,另⼀端称为栈底。栈中的数据元素遵守后进先出LIFO(LastInFirstOut)的原则。

压栈:栈的插⼊操作叫做进栈/压栈/⼊栈,⼊数据在栈顶。

出栈:栈的删除操作叫做出栈。出数据在栈顶。

2.栈的使用

这里我们直接调用标准库里面的类,给大家看下效果

代码如下:

java 复制代码
import java.util.Stack;

//利用标准库里面的stack来测试栈
public class StackDemo {
    public static void main(String[] args) {
        Stack<Integer> stack = new Stack<>();
        //入栈1-2-3-4
        stack.push(1);
        stack.push(2);
        stack.push(3);
        stack.push(4);

        //出栈4-3-2-1
        System.out.println(stack.pop());
        System.out.println(stack.pop());
        System.out.println(stack.pop());
        System.out.println(stack.pop());

        //取栈顶元素4
        //System.out.println(stack.peek());

        //检查栈是否为空
        if (stack.empty()){
            System.out.println("栈为空");
        }else {
            System.out.println("栈不为空");
        }

    }
}

结果:

3.栈的模拟实现

从上图中可以看到,Stack继承了Vector,Vector和ArrayList类似,都是动态的顺序表,不同的是 Vector是线程安全的。

这里我们来手搓实现Stack,这里我们是基于顺序表来实现的

java 复制代码
//基于顺序表,手搓栈
public class MyStack {
    public int[] array;
    public int size;

    public MyStack() {
        array=new int[1000];
        size=0;
    }

    //扩容
    public void reallocate(){
        int[] newArray =new int[array.length*2];
        for (int i=0;i<size;i++){
            newArray[i] = array[i];
        }
        this.array=newArray;
    }

    //入栈,本质就是尾插
    public void push(int value){
        //先判断空间是否还够,不够就扩容
        if (size>=array.length){
            reallocate();
        }
        array[size]=value;
        size++;
    }

    //出栈,本质就是尾删
    public int pop(){
        if (size==0){
            throw new RuntimeException("栈为空");
        }
        int ret = array[size-1];
        size--;
        return ret;
    }

    //取栈顶元素
    public int peek(){
        if (size==0){
            throw new RuntimeException("栈为空");
        }
        return array[size-1];
    }

    public static void main(String[] args) {
        MyStack stack = new MyStack();

        stack.push(1);
        stack.push(2);
        stack.push(3);
        stack.push(4);
        
        System.out.println(stack.pop());
        System.out.println(stack.pop());
        System.out.println(stack.pop());
        System.out.println(stack.pop());

        System.out.println(stack.peek());
    }
}

输出结果是一样的,这里我就不给结果了!!!

二:队列(Queue)

1.概念

队列:只允许在⼀端进⾏插⼊数据操作,在另⼀端进⾏删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out)⼊队列:进⾏插⼊操作的⼀端称为队尾(Tail/Rear)出队列:进⾏删除操作 的⼀端称为队头(Head/Front)

2.队列的使⽤

在Java中,Queue是个接⼝,底层是通过链表实现的。

注意:Queue是个接⼝,在实例化时必须实例化LinkedList的对象,因为LinkedList实现了Queue接 ⼝。

这里我们通过标准库来实现队列,看看效果

代码如下:

java 复制代码
import java.util.LinkedList;
import java.util.Queue;

//利用标准库Queue完成队列测试
public class QueueDemo {
    public static void main(String[] args) {
        Queue<Integer> queue = new LinkedList<>();

        //入队
        queue.offer(1);
        queue.offer(2);
        queue.offer(3);
        queue.offer(4);
        System.out.println(queue);

        //出队
        System.out.println(queue.poll());
        System.out.println(queue.poll());
        System.out.println(queue.poll());
        System.out.println(queue.poll());

        //取队首元素
        System.out.println(queue.peek());

        //判断是否为空
        if (queue.isEmpty()){
            System.out.println("链表为空");
        }else
            System.out.println("链表不为空");
    }
}

输出结果:

3.队列模拟实现

队列中既然可以存储元素,那底层肯定要有能够保存元素的空间,通过前⾯线性表的学习了解到常⻅ 的空间类型有两种:顺序结构和链式结构。

这里我们基于单链表来手搓一个队列

代码如下:

java 复制代码
//基于单链表,手搓一个队列
class LinkedNode{
    public int val;
    public LinkedNode next;

    public LinkedNode(int val) {
        this.val = val;
        this.next=null;
    }
}

//表示整个队列
public class MyQueue {
    public LinkedNode head = null;
    public LinkedNode tail =null;

    //入队列,即尾插
    public void offer(int val){
        LinkedNode newNode = new LinkedNode(val);

        //链表为空的情况
        if (head==null){
            head=newNode;
            tail=newNode;
            return;
        }

        //链表非空情况
        tail.next=newNode;
        tail=tail.next;
    }

    //出队列,即头删
    public Integer poll(){
        if (head==null){
            return null;
        }

        int ret = head.val;
        head=head.next;
        return ret;
    }

    //取队首元素
    public Integer peek(){
        if (head==null){
            return null;
        }

        return head.val;
    }

    public static void main(String[] args) {
        MyQueue queue =new MyQueue();

        queue.offer(1);
        queue.offer(2);
        queue.offer(3);
        queue.offer(4);

//        System.out.println(queue.poll());
//        System.out.println(queue.poll());
//        System.out.println(queue.poll());
//        System.out.println(queue.poll());

        System.out.println(queue.peek());
    }
}

三:双端队列(Deque)

双端队列(deque)是指允许两端都可以进⾏⼊队和出队操作的队列,deque是"doubleended queue"的简称。那就说明元素可以从队头出队和⼊队,也可以从队尾出队和⼊队。

Deque是⼀个接⼝,使⽤时必须创建LinkedList的对象。

在实际⼯程中,使⽤Deque接⼝是⽐较多的,栈和队列均可以使⽤该接⼝

1.双端队列的使用

这里我们同样利用标准库里面的类,来看看双端队列的效果,基于顺序表

java 复制代码
import java.util.ArrayDeque;
import java.util.Deque;

public class DequeDemo {
    public static void main(String[] args) {
        // 创建一个双端队列
        Deque<String> deque = new ArrayDeque<>();

        System.out.println("--- 双端队列 (Deque) 操作演示 ---");
        System.out.println("初始状态: " + deque);

        // 1. 从队尾添加元素 (等同于 offerLast())
        deque.offer("Orange");
        System.out.println("使用 offer() 从队尾添加 'Orange' 后: " + deque);

        // 2. 从队头添加元素
        deque.offerFirst("Apple");
        System.out.println("使用 offerFirst() 从队头添加 'Apple' 后: " + deque);

        // 3. 从队尾添加元素
        deque.offerLast("Banana");
        System.out.println("使用 offerLast() 从队尾添加 'Banana' 后: " + deque);

        // 4. 查看队头元素 (不移除)
        String frontElement = deque.peek();
        System.out.println("使用 peek() 查看队头元素: " + frontElement);

        // 5. 查看队尾元素 (不移除)
        String lastElement = deque.peekLast();
        System.out.println("使用 peekLast() 查看队尾元素: " + lastElement);

        // 6. 从队头移除元素
        String removedFirst = deque.poll();
        System.out.println("使用 poll() 移除队头元素 '" + removedFirst + "' 后: " + deque);

        // 7. 从队尾移除元素
        String removedLast = deque.pollLast();
        System.out.println("使用 pollLast() 移除队尾元素 '" + removedLast + "' 后: " + deque);
    }
}

输出;

以上就是我们的全部内容了!!!

相关推荐
j7~1 小时前
【C语言】《C语言自定义类型(结构体+联合体+枚举类型)》--详解
c语言·开发语言·深度学习·结构体·位段·联合体·枚举类型
Escalating_xu1 小时前
C++11 彻底吃透 emplace_back 与 push_back(最全闭环:左右值|深浅拷贝|移动构造|万能引用|完美转发)
开发语言·c++
春生野草2 小时前
个人笔记--大顶堆和基数排序
java·数据结构·算法
高铭杰2 小时前
Golang sync.Mutex实现原理学习
java·学习·golang
皓月斯语2 小时前
B3865 [GESP202309 二级] 小杨的 X 字矩阵 题解
开发语言·c++·矩阵·题解
paeamecium4 小时前
【PAT甲级真题】- Rational Sum (20)
数据结构·c++·python·算法·pat考试·pat
Highcharts.js10 小时前
教程:基于 React + Highcharts 构建一个单页应用程序、按需数据拉取与图表渲染
开发语言·前端·数据结构·react.js·前端框架·highcharts·页面应用
头发还在的女程序员11 小时前
医院陪诊管理系统怎么选择?——2026 年选型避坑与架构参考
java·开发语言·陪诊系统·陪诊app·医院陪诊陪护
CodeStats12 小时前
【Spring事务】Spring事务注解 @Transactional 完整体系:从 MySQL 隔离级别到 MyBatis 原理详解
java·spring·mybatis·事务·transactional