[数据结构]栈和队列

【本节目标】

  1. 栈的概念及使用
  2. 队列的概念及使用

在这里插入图片描述

一、栈(Stack):后进先出(LIFO)的数据结构

1.1 栈的基本概念

栈是一种遵循后进先出(Last In First Out, LIFO)原则的线性数据结构。想象一叠盘子,你总是把新盘子放在最上面(LI),取盘子时也从最上面开始取(FO)。

在这里插入图片描述

1.2 栈的核心操作

栈通常支持以下几种基本操作:

  • push:将元素压入栈顶
  • pop:移除并返回栈顶元素
  • peek/top:查看栈顶元素但不移除
  • isEmpty:检查栈是否为空
  • size:获取栈中元素数量
public static void main(String[] args) {
    MyStack stack = new MyStack();
    stack.push(12);
    stack.push(23);
    stack.push(34);
    stack.push(45);

    System.out.println(stack.pop());//12
    System.out.println(stack.pop());//23
    System.out.println(stack.pop());//34
    System.out.println("=========");
    System.out.println(stack.peek());//45
}

1.3 栈的模拟实现

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

在这里插入图片描述

public class MyStack {

    public int[] elem;
    public int usedSize;

    public MyStack() {
        this.elem = new int[10];
    }

    public void push(int val){
        if (isFull()){
            this.elem = Arrays.copyOf(elem,2*elem.length);
        }
        elem[usedSize++] = val;
    }
    public boolean isFull(){
        return usedSize == elem.length;
    }
    public int pop(){
        if (isFull()){
            throw new EmptyStackException();
        }
        int val = elem[usedSize - 1];
        usedSize--;
        return val;
    }
    public int peek(){
        if (isEmpty()){
            throw new EmptyStackException();
        }
        return elem[usedSize - 1];
    }
    public boolean isEmpty(){
        return usedSize == 0;
    }
}

二、队列(Queue):先进先出(FIFO)的数据结构

2.1 队列的基本概念

队列是一种遵循先进先出(First In First Out, FIFO)原则的线性数据结构。想象排队买票,先来的人先得到服务(FI),后来的人排在队尾(FO)。

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

在这里插入图片描述

2.2 队列的核心操作

队列通常支持以下几种基本操作:

  • enqueue:将元素加入队尾
  • dequeue:移除并返回队首元素
  • front/peek:查看队首元素但不移除
  • isEmpty:检查队列是否为空
  • size:获取队列中元素数量
public static void main4(String[] args) {
    Queue<Integer> queue = new LinkedList<>();
    LinkedList<Integer> queue2 = new LinkedList<>();
    queue.offer(1);
    queue.offer(2);
    queue.offer(3);
    queue.offer(4);

    System.out.println(queue.poll());//1
    System.out.println(queue.peek());//2
}

2.3 队列模拟实现

在这里插入图片描述

public class MyQueue {
    static class ListNode{
        public int val;
        public ListNode prev;
        public ListNode next;

        public ListNode(int val) {
            this.val = val;
        }
    }

    public ListNode first = null;
    public ListNode last = null;

    public int usedSize = 0;
    public void offer(int val){
        ListNode node = new ListNode(val);
        if (isEmpty()){
            first = last = node;
        }else{
            last.next = node;
            node.prev = last;
            last = last.next;
        }
        usedSize++;
    }

    public int poll(){
        if (isEmpty()){
            return -1;
        }
        int val = first.val;
        first = first.next;
        if (first != null){
            first.prev = null;
        }
        return val;
    }
    public int peek(){
        if (isEmpty()){
            return -1;
        }
        return first.val;
    }
    public boolean isEmpty(){
        return usedSize == 0;
//        return first == null;
    }
}

2.4 循环队列

实际中我们有时还会使用一种队列叫循环队列。如操作系统课程讲解生产者消费者模型时可以就会使用循环队列。 环形队列通常使用数组实现。

在这里插入图片描述

如何区分空与满

  1. 通过添加 size 属性记录
  2. 保留一个位置
  3. 使用标记

三.双端队列 (Deque)

是指允许两端都可以进行入队和出队操作的队列,deque 是 “double ended queue” 的简称。 那就说明元素可以从队头出队和入队,也可以从队尾出队和入队。

Deque是一个接口,使用时必须创建LinkedList的对象。

在这里插入图片描述

四、栈与队列的比较

特性栈(Stack)队列(Queue)
原则LIFO (后进先出)FIFO (先进先出)
插入操作push (栈顶)enqueue (队尾)
删除操作pop (栈顶)dequeue (队首)
访问操作peek (栈顶)front (队首)
典型应用函数调用、撤销操作、DFS任务调度、消息队列、BFS
实现复杂度相对简单需要考虑队首和队尾
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值