欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > 能源 > 栈和队列相关知识题目

栈和队列相关知识题目

2025/3/29 15:17:34 来源:https://blog.csdn.net/A18266678650/article/details/146512110  浏览:    关键词:栈和队列相关知识题目

栈的底层原理

栈(Stack)是一种后进先出(LIFO)​的线性数据结构,所有操作(如插入、删除)仅在栈顶进行。它的底层实现可以是数组或链表,具体取决于编程语言和应用场景。

1.基于数组实现:使用连续内存的数组存储元素,通过一个指针(如 top)标记栈顶位置。

核心操作:入栈(Push)​:将元素放入 top 位置,top 指针后移。​

出栈(Pop)​:返回 top-1 位置的元素,top 指针前移。

2. 基于链表(链式存储):使用单向链表(头插法)存储元素,链表的头节点作为栈顶。

入栈(Push)​:将新节点插入链表头部。

出栈(Pop)​:删除链表头节点并返回其值。

栈的应用场景

函数调用与递归:操作系统自动管理函数调用栈。
​括号匹配:检查表达式中的括号是否成对。
​表达式求值:中缀表达式转后缀表达式(逆波兰式)。
​撤销操作(Undo)​:编辑器中的操作历史栈。
​深度优先搜索(DFS)​:用栈保存遍历路径

对应题目 

用栈实现队列用栈实现队列用栈实现队列

思想:用两个栈来模拟队列,由于队列是先进先出,所以设置两个栈,一个入队栈,一个出队栈

import java.util.Deque;
import java.util.ArrayDeque;class MyQueue {private Deque<Integer> inputStack;private Deque<Integer> outputStack;public MyQueue() {inputStack = new ArrayDeque<>();outputStack = new ArrayDeque<>();}// 入队:直接压入输入栈public void push(int x) {inputStack.push(x);}// 出队:若输出栈为空,先转移元素public int pop() {if (outputStack.isEmpty()) {transferInputToOutput();}return outputStack.pop();}// 查看队首元素:类似出队但不删除public int peek() {if (outputStack.isEmpty()) {transferInputToOutput();}return outputStack.peek();}// 判断队列是否为空public boolean empty() {return inputStack.isEmpty() && outputStack.isEmpty();}// 将输入栈元素转移到输出栈(反转顺序)private void transferInputToOutput() {while (!inputStack.isEmpty()) {outputStack.push(inputStack.pop());}}
}

用队列实现栈用队列实现栈用队列实现栈用队列实现栈

思想:队列模拟栈,使用两个队列来模拟,一个主队列,一个副队列

核心思想
  • 维护两个队列:一个主队列(mainQueue)和一个辅助队列(tempQueue)。
  • 入栈(Push)​:直接将元素加入主队列。
  • 出栈(Pop)​:将主队列中除最后一个元素外的所有元素转移到辅助队列,弹出最后一个元素,最后交换主队列和辅助队列的角色。
操作步骤
  1. Push(入栈)​
    • 将新元素直接加入主队列。
  2. Pop(出栈)​
    • 将主队列中的前 n-1 个元素依次出队并加入辅助队列。
    • 弹出主队列的最后一个元素(即栈顶元素)。
    • 交换主队列和辅助队列的角色,以便下次操作。
    • import java.util.LinkedList;
      import java.util.Queue;class MyStack {private Queue<Integer> mainQueue;private Queue<Integer> tempQueue;public MyStack() {mainQueue = new LinkedList<>();tempQueue = new LinkedList<>();}// 入栈:直接加入主队列public void push(int x) {mainQueue.offer(x);}// 出栈:转移前n-1个元素后弹出最后一个元素public int pop() {while (mainQueue.size() > 1) {tempQueue.offer(mainQueue.poll());}int top = mainQueue.poll();// 交换主队列和辅助队列Queue<Integer> swap = mainQueue;mainQueue = tempQueue;tempQueue = swap;return top;}// 查看栈顶元素:逻辑同pop,但需将元素重新放回主队列public int top() {while (mainQueue.size() > 1) {tempQueue.offer(mainQueue.poll());}int top = mainQueue.poll();tempQueue.offer(top); // 重新加入队列// 交换队列Queue<Integer> swap = mainQueue;mainQueue = tempQueue;tempQueue = swap;return top;}// 判空:主队列是否为空public boolean empty() {return mainQueue.isEmpty();}
      }

有效的括号有效的括号

思想:括号匹配是使用栈解决的经典问题。遇见左括号就压入栈中,遇见右括号,先判断栈是否为空,在导出栈顶元素判断,若最后栈为空则说明符号匹配成功,若左右括号不匹配也返回失败。

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

删除字符串中的所有相邻重复项 

思想:比较简单,需要注意一个点就是,栈无法直接转化成数组,即stack.toString()是错误的
要创建数组,将栈中的元素都出栈即可

class Solution {public String removeDuplicates(String s) {Stack<Character> stack =new Stack<>();for(int i=0;i<s.length();i++){char c = s.charAt(i);if(stack.isEmpty() || c != stack.peek()){stack.push(c);}else {stack.pop();}}String str = "";//剩余的元素即为不重复的元素while (!stack.isEmpty()) {str = s.pop() + str;}return str;}
}

逆波兰表达式求值

要注意下述代码中的几个问题:
1.因为字符串表示的是整数的加减乘除运算,所以定义栈的时候要采取整型Stack<Integer> stack =new Stack<>();
2.定义两个变量分别存储前两个操作数,但要注意操作数的顺序,因为先进后出,所以第一个出来的是第二个操作数
3.巧用switch分支结构,先做判断,在压入栈
4.最后不是输出整个栈的元素,方法要求的返回表达式值的整数,所以要做类型转换Integer.valueOf(token)

5.由于leetcode 内置jdk的问题,不能使用==判断字符串是否相等,只能用equals。并且字符相等用双引号

class Solution {public int evalRPN(String[] tokens) {Stack<Integer> stack =new Stack<>();int a,b,c;for(String token :tokens){if(token.equals("+") || token.equals("-") || token.equals("*") || token.equals("/") ){b = stack.pop();//第二个操作数a = stack.pop();//第一个操作数c = switch(token){case "+" -> a+b;case "-" -> a-b;case "*" -> a*b;case "/" -> a/b;default ->  0;};stack.push(c);}else {stack.push(Integer.valueOf(token));}}return stack.pop();}
}

有效的括号用队列实现栈用队列实现栈用队列实现栈

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词