栈(stack)和队列(queue)

特殊的线性表,只允许在一端进行插入和删除元素的操作,遵循先入后出的原则。

 自己生成一个栈以及其方法

//添加元素
    public void push(int val){
        if (isFull()){
            elem= Arrays.copyOf(elem,2*elem.length);
        }
        elem[useSize]=val;
        useSize++;
    }

    //判满操作
    public boolean isFull(){
        if (useSize==elem.length){
            return true;
        }
        return false;
    }

    //删除元素
    public int pop(){
        if (isEmpty()){
            throw new EmptyStackExpextion("数组越界异常");
        }
        int oldVal=elem[useSize-1];
        useSize--;
        return oldVal;
    }

    //判空操作
    public boolean isEmpty(){
        return useSize==0;
    }

    //获取栈顶元素
    public int peek(){
        if (isEmpty()){
            throw new EmptyStackExpextion("栈为空了");
        }
        return elem[useSize-1];
    }

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

如果用单向链表表示栈,建议使用头插法:

入栈:O(1),从头结点插入不需要遍历列表

出栈:O(1),删除头结点

如果用双向链表表示:

从头入栈,从头出栈;从尾入栈,从尾出栈

例题:根据 逆波兰表示法,求表达式的值。

有效的算符包括 +-*/ 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。

https://leetcode.cn/problems/evaluate-reverse-polish-notation/description/

class Solution {
    public int evalRPN(String[] tokens) {
        Deque<Integer> stack = new LinkedList<Integer>();
        int n = tokens.length;
        for (int i = 0; i < n; i++) {
            String token = tokens[i];
            if (isNumber(token)) {
                stack.push(Integer.parseInt(token));
            } else {
                int num2 = stack.pop();
                int num1 = stack.pop();
                switch (token) {
                    case "+":
                        stack.push(num1 + num2);
                        break;
                    case "-":
                        stack.push(num1 - num2);
                        break;
                    case "*":
                        stack.push(num1 * num2);
                        break;
                    case "/":
                        stack.push(num1 / num2);
                        break;
                    default:
                }
            }
        }
        return stack.pop();
    }

    public boolean isNumber(String token) {
        return !("+".equals(token) || "-".equals(token) || "*".equals(token) || "/".equals(token));
    }
}

时间复杂度:O(n),其中 n是数组 tokens的长度。需要遍历数组 tokens 一次,计算逆波兰表达式的值。

空间复杂度:O(n),其中 n是数组 tokens的长度。使用栈存储计算过程中的数,栈内元素个数不会超过逆波兰表达式的长度。

输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。

1. 0<=pushV.length == popV.length <=1000

2. -1000<=pushV[i]<=1000

3. pushV 的所有数字均不相同

https://www.nowcoder.com/practice/d77d11405cc7470d82554cb392585106?tpId=13&tqId=11174&ru=/exam/oj

    if (pushA. length != popA.length){ 
        return false;
    }
    Stack<Integer> stack=new Stack<>();
    int j=0;
    for(int i=O;i<pushA. length;i++){
    stack.push(pushA[i]);
    while(j<popA.length && !stack.empty() && stack.peek()=-popA[j]){}
        stack.pop();
        j++;
        }
    return stack. empty();
    

队列

是一个特殊线性表,只允许从一端插入数据,在另一端进行删除数据,遵循先进先出的原则。

队列的方法

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

    //出队
    public int poll(){
        if (head==null){
            return -1;
        }
        int oldVal=head.val;
        if (head.next==null){
            head=null;
            tail=null;
        }else {
            head=head.next;
        }
        return oldVal;
    }

    //查看队首元素
    public int peek(){
        if (head==null){
            return -1;
        }
        return head.val;
    }

循环队列

class MyCircularQueue {
    public int[] elem;
    public int front;//队头下标
    public int rear;//队尾下标

    public MyCircularQueue(int k) {
        this.elem=new int[k+1];
    }
    
    public boolean enQueue(int value) {
        if(isFull()){
            return false;
        }
        this.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;
        }
        int index=(rear==0)?elem.length-1:rear-1;
        return elem[index];
    }
    
    public boolean isEmpty() {
        return rear==front;
    }
    
    public boolean isFull() {
        return (rear+1)%elem.length==front;
    }
}

用队列实现栈

  • void push(int x) 将元素 x 压入栈顶。
  • int pop() 移除并返回栈顶元素。
  • int top() 返回栈顶元素。
  • boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。
class MyStack {
    public int useSize;
    Queue<Integer> qu1;
    Queue<Integer> qu2;
    
    public MyStack() {
        qu1=new LinkedList<>();
        qu2=new LinkedList<>();
    }
    
    public void push(int x) {
        if(!qu1.isEmpty()){
            qu1.offer(x);
        }else if(!qu2.isEmpty()){
            qu2.offer(x);
        }else{
            qu1.offer(x);
        }
        useSize++;
    }
    
    public int pop() {
        if(empty()){
            return -1;
        }
        if(!qu1.isEmpty()){
            int curSize=qu1.size();
            for(int i=0;i<curSize-1;i++){
                qu2.offer(qu1.poll());
            }
            useSize--;
            return qu1.poll();
        }else{
            int curSize=qu2.size();
            for(int i=0;i<curSize-1;i++){
                qu1.offer(qu2.poll());
            }
            useSize--;
            return qu2.poll();
        }
    }
    
    public int top() {
        if(empty()){
            return -1;
        }
        if(!qu1.isEmpty()){
            int curSize=qu1.size();
            int ret=-1;
            for(int i=0;i<curSize;i++){
                ret=qu1.poll();
                qu2.offer(ret);
            }
            return ret;
        }else{
            int curSize=qu2.size();
            int ret=-1;
            for(int i=0;i<curSize;i++){
                ret=qu2.poll();
                qu1.offer(ret);
            }
            return ret;
        }
    }
    
    public boolean empty() {
        return useSize==0;
    }
}

用栈实现队列

  • void push(int x) 将元素 x 推到队列的末尾
  • int pop() 从队列的开头移除并返回元素
  • int peek() 返回队列开头的元素
  • boolean empty() 如果队列为空,返回 true ;否则,返回 false
class MyQueue {
    Stack<Integer> s1;
    Stack<Integer> s2;

    public MyQueue() {
        s1=new Stack<>();
        s2=new Stack<>();
    }
    
    public void push(int x) {
        s1.push(x);
    }
    
    public int pop() {
        if(empty()){
            return -1;
        }
        if(s2.empty()){
            while(!s1.empty()){
                s2.push(s1.pop());
            }
        }
        return s2.pop();
    }
    
    public int peek() {
        if(empty()){
            return -1;
        }
        if(s2.empty()){
            while(!s1.empty()){
                s2.push(s1.pop());
            }
        }
        return s2.peek();
    }
    
    public boolean empty() {
        return s1.empty() && s2.empty();
    }
}

实现最小栈

  • MinStack() 初始化堆栈对象。
  • void push(int val) 将元素val推入堆栈。
  • void pop() 删除堆栈顶部的元素。
  • int top() 获取堆栈顶部的元素。
  • int getMin() 获取堆栈中的最小元素。
class MinStack {

    private Stack<Integer> s;
    private Stack<Integer> minStack;

    public MinStack() {
        s=new Stack<>();
        minStack=new Stack<>();
    }
    
    public void push(int val) {
        s.push(val);
        if(!minStack.empty()){
            int peekV=minStack.peek();
            if(val<=peekV){
                minStack.push(val);
            }
        }else{
            minStack.push(val);
        }
    }
    
    public void pop() {
        if(!s.empty()){
            int popV=s.pop();
            int peekVMin=minStack.peek();
            if(popV==peekVMin){
                minStack.pop();
            }
        }
    }
    
    public int top() {
        if(!s.empty()){
            return s.peek();
        }
        return 0;
    }
    
    public int getMin() {
        if(!minStack.empty()){
            return minStack.peek();
        }
        return 0;
    }
}

 

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值