栈 和 队列


概念

只能在表的一端进行插入和删除运算的线性表
进行插入和删除运算的一端叫栈顶,另一端叫栈底
栈中的数据按照先进后出(FILO)或后进先出(LIFO)的原则

在这里插入图片描述

进栈:在栈顶插入数据,叫做入栈/进栈/压栈。
出栈:在栈顶删除数据,叫做出栈。
栈的基本操作:建栈,入栈,出栈,读栈顶元素,判断栈空,栈满等

栈的顺序存储

在这里插入图片描述

栈空时 usedSize == 0
栈满时 usedSize == elem.length

public class MyStack {

    public int[] elem;
    public int usedSize;

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

    //压栈
    public void push(int val) {
        if (isFull()) {
            //扩容 2倍
            elem = Arrays.copyOf(elem,2*elem.length);
        }
        elem[usedSize++] = val;
    }
    //判断是否满了
    public boolean isFull() {
        return usedSize == elem.length;
    }

    //出栈
    public int pop() {
        if(isEmpty()) {
            throw new EmptyException("栈是空的!");
        }
        return elem[--usedSize];
    }
    
    //判断是否为空
    public boolean isEmpty() {
        return usedSize == 0;
    }

    //查看栈顶元素
    public int peek() {
        if(isEmpty()) {
            throw new EmptyException("栈是空的!");
        }
        return elem[usedSize - 1];
    }
    
}

public class EmptyException extends RuntimeException{
    public EmptyException(String message) {
        super(message);
    }
}

栈的链式存储

在这里插入图片描述

head 结点为null时 栈空

public class MyStack1 {

    // 结点
    static class Node {
        public int val;
        public Node next;
        public Node(int val) {
            this.val = val;
        }
    }

    public Node head;
    public int usedSize;

    //压栈
    public void push(int val) {
        Node node = new Node(val);
        if (head == null) {
            head = node;
        } else {
            node.next = head;
            head = node;
        }
        usedSize++;
    }

    //出栈
    public int pop() {
        if(isEmpty()) {
            throw new EmptyException("栈是空的!");
        }
        int ret = head.val;
        head = head.next;
        usedSize--;
        return ret;
    }

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

    //查看栈顶元素
    public int peek() {
        if(isEmpty()) {
            throw new EmptyException("栈是空的!");
        }
        return head.val;
    }

}

队列

概念

队列是一种先进先出(FIFO)的线性表.
它只允许在表的一端进行插入(队尾)
而在另一端删除元素 (队头)

在这里插入图片描述

循环队列

用一个数组来实现队列, front表示队头下标,rear表示队尾下标
初始状态是front=rear=0
入队时rear+1
出队时front+1

在这里插入图片描述

出队后front+1,front前面的空间就不能用了,会导致假溢出
下图中,还有一个空间,但是不能再入队了
在这里插入图片描述

所以就提出了循环队列,让下标循环起来
牺牲一个空间来区分队列空和队列满

在这里插入图片描述

// 循环队列
public class MyCircularQueue {

    private int[] elem;
    private int front;
    private int rear;

    public MyCircularQueue(int k) {
        elem = new int[k + 1];
    }

    // 入队
    public boolean enQueue(int value) {
        if (isFull()) {
            return false;
        }
        elem[rear] = value;
        rear = (rear + 1) % elem.length;
        return true;
    }

    // 出队
    public boolean deQueue() {
        if (isEmpty()) {
            return false;
        }
        front = (front + 1) % elem.length;
        return true;
    }

    // 获取队首元素
    public int Front() {
        if (isEmpty()) {
            return -1;
        }
        return elem[front];
    }

    // 获取队尾元素
    public int Rear() {
        if (isEmpty()) {
            return -1;
        }
        return elem[(rear - 1 + elem.length) % elem.length];
    }

    // 是否为空
    public boolean isEmpty() {
        return front == rear;
    }

    // 是否已满
    public boolean isFull() {
        //浪费一个空间来区分 队列空 和 队列满
        return (rear + 1) % elem.length == front;
    }
}

链队列

在这里插入图片描述

public class MyQueue {

    static class Node {
        public int val;
        public Node next;

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

    public Node head;
    public Node last;
    public int usedSize;

    //入队
    public void offer(int val) {
        Node node = new Node(val);
        if (head == null) {
            head = node;
            last = node;
        } else {
            last.next = node;
            last = node;
        }
        usedSize++;
    }

    //出队
    public int poll() {
        if(empty()) {
            throw new EmptyException("队列为空");
        }
        int ret = head.val;
        head = head.next;
        if (head == null) {
            //只有一个结点,出队后就没了,last也置空
            last = null;
        }
        usedSize--;
        return ret;
    }

    // 是否为空
    public boolean empty() {
        return usedSize == 0;
    }

    // 查看队首
    public int peek() {
        if(empty()) {
            throw new EmptyException("队列为空");
        }
        return head.val;
    }

    //大小
    public int size() {
        return usedSize;
    }

    public void clear() {
        head = null;
        last = null;
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值