模拟实现栈和队列的有关代码和经典习题

本文介绍了栈这种数据结构,它是一种后进先出(LIFO)的线性表,支持压栈和出栈操作。栈在括号匹配和逆波兰表达式求值等问题中有着重要应用。同时,文章也讨论了队列,包括基本的入队和出队操作,以及用链表实现队列和循环队列的概念。
摘要由CSDN通过智能技术生成
:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO Last In First Out )的原则。
压栈:栈的插入操作叫做进栈 / 压栈 / 入栈, 入数据在栈顶

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

栈的方法

方法 功能 Stack() 构造一个空栈 E push(E e) 将e入栈,并返回e E pop()

将栈顶元素出栈并返回

E peek() 获取栈顶元素 int size() 获取栈中有效元素的个数 boolean empty() 检测栈是否为空

Stack():

    private int[] elem;
    private int usedSize;

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

push(e):

    public void push(int val) {
        if(isFull()) {
           elem = Arrays.copyOf(elem,2*elem.length);
        }
        elem[usedSize] = val;
        usedSize++;
    }

pop():

    public int pop() {
        if(empty()) {
            //抛出异常
            throw new StackEmptyException("栈为空!");
        }
        return elem[--usedSize];
    }

peek():

   public int peek() {
        if(empty()) {
            //抛出异常!!
            throw new StackEmptyException("栈为空!");
        }
        return elem[usedSize-1];
    }

size():

public int size(){
    return usedSize;
}

empty():

    public boolean empty() {
        return usedSize == 0;
    }

栈的经典题:

括号匹配问题:

class Solution {
    public boolean isValid(String s) {
        Stack<Character> stack = new Stack<>();
        for(int i = 0;i < s.length();i++) {
            char ch = s.charAt(i);
            if(ch == '(' || ch == '[' || ch == '{') {
                stack.push(ch);
            }else {
                if(stack.empty()){
                    return false;
                }else {
                    char tmp = stack.peek();
                    if(ch == ')' && tmp == '(' || ch == ']' && tmp == '[' || ch == '}' && tmp == '{'){
                        stack.pop();
                    }else {
                        return false;
                    }
                }
            }
        }
        if(!stack.empty()){
            return false;
        }
        return true;
    }
}

逆波兰表达式求值:

class Solution {
    public int evalRPN(String[] tokens) {
        Stack<Integer> stack = new Stack<>();
        for(String s : tokens) {
            if(isNumber(s)){
                stack.push(Integer.parseInt(s));
            } else {
                int num2 = stack.pop();
                int num1 = stack.pop();
                switch(s){
                    case"+":
                        stack.push(num1 + num2);
                        break;
                    case"-":
                        stack.push(num1 - num2);
                        break;
                    case"*":
                        stack.push(num1 * num2);
                        break;
                    case"/":
                        stack.push(num1 / num2);
                        break;   
                }
            }
        }
        return stack.pop();
    }
    public boolean isNumber(String s){
        if(s.equals("+") || s.equals("-") || s.equals("*") || s.equals("/")){
            return false;
        }
        return true;
    }
}

出栈和入栈的次序匹配:

import java.util.*;
public class Solution {
    public boolean IsPopOrder(int [] pushA,int [] popA) {
        Stack<Integer> stack = new Stack<>();
        int j = 0;
        for(int x : pushA) {
            stack.push(x);
            while(!stack.empty()  && j < pushA.length && stack.peek() == popA[j]) {
                stack.pop();
                j++;
            }
        }
        return stack.empty();
    }
}

最小栈:

class MinStack {
    private Stack<Integer> stack;
    private Stack<Integer> minStack;


    public MinStack() {
        stack = new Stack<>();
        minStack = new Stack<>();
    }
    
    public void push(int val) {
        stack.push(val);
        if(minStack.empty()){
            minStack.push(val);
        } else {
            if(val <= minStack.peek()) {
                minStack.push(val);
            }
        }
    }
    
    public void pop() {
        if(stack.empty()){
            return;
        }
        int val = stack.pop();
        if(val == minStack.peek()){
            minStack.pop();
        }
    }
    
    public int top() {
        if(stack.empty()){
            return -1;
        }
        return stack.peek();
    }
    
    public int getMin() {
        return minStack.peek();
    }
}

队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out)

入队列:进行插入操作的一端称为队尾(Tail/Rear)

出队列:进行删除操作的一端称为队头 (Head/Front)

队列的方法
方法功能
boolean offer(E e)入队列

E poll()

出队列
peek()获取队头元素
int size()获取队列中有效元素个数
boolean isEmpty()检测队列是否为空

用链表模拟实现队列:

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

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

    private int usedSize;

offer( ):

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

poll():

    public int poll() {
        if(head == null) {
            return -1;
        }
        int val = -1;
        if(head.next == null) {
            val = head.val;
            head = null;
            last = null;
            return val;
        }
        val = head.val;
        head = head.next;
        usedSize--;
        return val;
    }

peek():

    public int peek() {
        if(head == null) {
            return -1;
        }
        return head.val;
    }

size():

    public int getUsedSize() {
        return usedSize;
    }

循环队列:

循环队列
方法功能
boolean enQueue()

入队

boolean deQueue()出队
int Front()获得队头元素
int Rear()获得队尾元素
boolean isEmpty()判断循环队列为空
boolean isFull()判断循环队列为满
    private int[] elem;
    private int front;//队头下标
    private int rear;//队尾下标

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

boolean enQueue():

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

boolean deQueue():

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

int Front():

    public int Front() {
        if(isEmpty()) {
            return -1;
        }
        return elem[front];
    }

int Rear():

    public int Rear() {
        if(isEmpty()) {
            return -1;
        }
        int index = (rear == 0) ? elem.length-1 : rear-1;
        return elem[index];
    }

boolean isEmpty():

    public boolean isEmpty() {
        return rear == front;
    }

boolean isFull():

    public boolean isFull() {
        return (rear+1) % elem.length == front;
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值