欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 明星 > 数据结构之栈和队列的应用

数据结构之栈和队列的应用

2024/10/24 7:31:32 来源:https://blog.csdn.net/zhj2003_/article/details/142132892  浏览:    关键词:数据结构之栈和队列的应用

目录

一、栈的应用

1. 括号匹配

 2. 计算后缀表达式

方法一(栈)

方法二(数组模拟栈)

二、队列应用

1. 二叉树层序遍历

方法一(队列)

三、总结


一、栈的应用

1. 括号匹配

给定一个只包括 '('')''{''}''['']' 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

  1. 左括号必须用相同类型的右括号闭合。
  2. 左括号必须以正确的顺序闭合。
  3. 每个右括号都有一个对应的相同类型的左括号。
class Solution {public boolean isValid(String s) {// 判断括号数是否匹配if (s.length() %2 == 1) {return false;}Stack<Character> S = new Stack();for (int i = 0; i < s.length(); ++i) {char ele = s.charAt(i);// 左括号if (containLeft(ele)) {S.push(ele);} else {if (S.empty()) {return false;}// 右括号if (CompareTo(S.peek(), ele)) {// 将栈顶元素弹出S.pop();} else {return false;}}}return S.empty() ? true : false;}// 包含左括号
public static boolean containLeft(char ch) {if (ch == '{') return true;if (ch == '(') return true;if (ch == '[') return true;return false;
}//  检验括号是否匹配public static boolean CompareTo(char forth, char latter) {if ((forth == '{' && latter == '}') || (forth == '(' && latter == ')') || (forth == '[' && latter == ']')) {return true;}return false;}
}   

 2. 计算后缀表达式

根据 逆波兰表示法,求该后缀表达式的计算结果。

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

说明:

  • 整数除法只保留整数部分。
  • 给定逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 0 的情况。

后缀表达式按照从左到右的运算规则,计算表达式需要一个栈存放操作数;假设表达式成立,依次获取每一个字符串,如果字符串是操作数,则直接入栈,如果字符串是操作符,出栈两次,首先出栈的是右操作数,后出栈的是左操作数,将运算得到的新操作数入栈。 

方法一(栈)

class Solution {public int evalRPN(String[] tokens) {Stack<Integer> S = new Stack<>();int i = 0;while (i < tokens.length) {String token = tokens[i++];if (isNumber(token)) {S.push(Integer.parseInt(token));} else {int num2 = S.pop();int num1 = S.pop();switch(token) {case "+":S.push(num1 + num2);break;case "-":S.push(num1 - num2);break;case "*":S.push(num1 * num2);break;case "/":S.push(num1 / num2);break;default:}}}return S.pop();}public boolean isNumber(String token) {return !("+".equals(token) || "-".equals(token) || "*".equals(token) || "/".equals(token));}
}

方法二(数组模拟栈)

class Solution {public int evalRPN(String[] tokens) {int n = tokens.length;int[] stack = new int[(n + 1) / 2];int index = -1;for (int i = 0; i < n; i++) {String token = tokens[i];switch(token) {case "+":index--;stack[index] += stack[index + 1];break;case "-":index--;stack[index] -= stack[index + 1];break;case "*":index--;stack[index] *= stack[index + 1];break;case "/":index--;stack[index] /= stack[index + 1];break;default:index++;stack[index] = Integer.parseInt(token);}}return stack[index];}
}

二、队列应用

1. 二叉树层序遍历

给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。

 /** public class TreeNode {*     int val;*     TreeNode left;*     TreeNode right;*     TreeNode() {}*     TreeNode(int val) { this.val = val; }*     TreeNode(int val, TreeNode left, TreeNode right) {*         this.val = val;*         this.left = left;*         this.right = right;*     }* }*/
public List<Integer> levelOrder(TreeNode node) {// 定义res存储结点的值List<Integer> res = new LinkedList<>();Queue<TreeNode> queue = new LinkedList<>();if (node != null) {queue.offer(node);}while (!queue.isEmpty()) {TreeNode ele = queue.poll();res.add(ele.val);// 判断结点是否有左右孩子if (ele.left != null) {queue.offer(ele.left);}if (ele.right != null) {queue.offer(ele.right);}}return res;
}

不同于题目的是,返回一个一维列表,但如果需要返回二维列表,我们不仅要实现层序遍历,还需要将同一层的结点放到一起。显然,上述的算法无法解决这个问题。


既然一个一个迭代无法满足要求,那么我们就可以考虑一层一层迭代。

我们定义一个队列,队列中存放同一层的结点。那么我们需要考虑如何迭代一层结点?

假设队列中存放了根节点root,此时队列的长度为1,那么我们迭代一次就可以让第一层所有结点出队。出队的同时,会将root的子节点存放到队列中。

此时队列的长度为2,我们迭代两次可以让第二层所有的结点出队,出队同时会让出队元素的子结点入队,且队列满足FIFO特点,因而可以保证从左至右遍历。

归纳总结可知,迭代的次数等于前一层的入队元素个数,因为出队同时要进队,因而前一层全部出队后,队列中的一定是当前层的元素,而且队列的长度一定等于当前层的结点个数,按照这个过程迭代,直至遍历完所有结点。

方法一(队列)

 /** public class TreeNode {*     int val;*     TreeNode left;*     TreeNode right;*     TreeNode() {}*     TreeNode(int val) { this.val = val; }*     TreeNode(int val, TreeNode left, TreeNode right) {*         this.val = val;*         this.left = left;*         this.right = right;*     }* }*/
class Solution {public List<List<Integer>> levelOrder(TreeNode root) {List<List<Integer>> res = new ArrayList();if (root == null) {return res;}Queue<TreeNode> queue = new LinkedList<TreeNode>();queue.offer(root);while (! queue.isEmpty()) {List<Integer> level = new ArrayList<>();int currentLevelSize = queue.size();for (int i = 0; i < currentLevelSize; ++i) {TreeNode node = queue.poll();level.add(node);if (node.left != null) {queue.offer(node.left);}if (node.right != null) {queue.offer(node.right);}}res.add(level);}return res;}
}

三、总结

栈和队列的应用十分广泛,本文简单地展示了这两种数据结构的特点,然而它的魅力不止这些,相信读者一定会遇到更加有趣的算法。上述内容如果有错误的地方,希望大佬们可以指正。我一直在学习的路上,您的帮助使我收获更大!觉得对您有帮助的话,还请点赞支持!我也会不断更新文章!

版权声明:

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

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