当前位置:   article > 正文

数据结构--栈

数据结构--栈

1,概念

栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈 顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。

压栈(push):栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。

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

栈在现实生活中的例子:

2 栈的使用 

  1. public static void main(String[] args) {
  2. Stack<Integer> s = new Stack();
  3. s.push(1);
  4. s.push(2);
  5. s.push(3);
  6. s.push(4);
  7. System.out.println(s.size()); // 获取栈中有效元素个数---> 4
  8. System.out.println(s.peek()); // 获取栈顶元素---> 4
  9. s.pop(); // 4出栈,栈中剩余1 2 3,栈顶元素为3
  10. System.out.println(s.pop()); // 3出栈,栈中剩余1 2 栈顶元素为3
  11. if(s.empty()){
  12. System.out.println("栈空");
  13. }else{
  14. System.out.println(s.size());
  15. }
  16. }

 如图:

 从上图中可以看到,Stack继承了Vector,Vector和ArrayList类似,都是动态的顺序表,不同的是Vector是线程安 全的。

3 模拟实现一个栈

  1. import java.util.Arrays;
  2. public class MyStack {
  3. public int[] elem;
  4. public int usedSize;
  5. public MyStack(){
  6. this.elem = new int[10];
  7. }
  8. public void push(int val){
  9. if(isFull()){
  10. //扩容
  11. elem = Arrays.copyOf(elem,2*elem.length);
  12. }
  13. elem[usedSize] = val;
  14. usedSize++;
  15. }
  16. public boolean isFull(){
  17. return usedSize == elem.length;
  18. }
  19. public int pop(){
  20. if(empty()){
  21. return -1;
  22. }
  23. int oldval = elem[usedSize-1];
  24. usedSize--;
  25. return oldval;
  26. }
  27. public int peek(){
  28. if(empty()){
  29. return -1;
  30. }
  31. int oldval = elem[usedSize-1];
  32. return oldval;
  33. }
  34. public boolean empty(){
  35. return usedSize == 0;
  36. }
  37. }
  1. public class Test {
  2. public static void main(String[] args) {
  3. MyStack myStack = new MyStack();
  4. myStack.push(1);
  5. myStack.push(2);
  6. myStack.push(3);
  7. System.out.println(myStack.pop());
  8. System.out.println(myStack.peek());
  9. }
  10. }

4 栈的应用场景

1. 改变元素的序列

1. 若进栈序列为 1,2,3,4 ,进栈过程中可以出栈,则下列不可能的一个出栈序列是(c)

: 1,4,3,2

B: 2,3,4,1

C: 3,1,4,2

D: 3,4,2,1

解析:1、2、3入栈以后,3再出栈,此时栈顶为2,只能出2,不能出其他

2.一个栈的初始状态为空。现将元素1、2、3、4、5、A、B、C、D、E依次入栈,然后再依次出栈,则元素出栈的顺 是( B)

A: 12345ABCDE

B: EDCBA54321

C: ABCDE12345

D: 54321EDCBA 

2  逆波兰表达式求值   OJ链接

题目:给你一个字符串数组 tokens ,表示一个根据 逆波兰表示法 表示的算术表达式。

请你计算该表达式。返回一个表示表达式值的整数

解题思路:

我们先来了解一下中缀表达式和后缀表达式:

  1. class Solution {
  2. public int evalRPN(String[] tokens) {
  3. Stack<Integer> stack = new Stack<>();
  4. for(int i = 0; i< tokens.length;i++){
  5. String tmp = tokens[i];
  6. if(!isOpearation(tmp)){
  7. Integer val = Integer.valueOf(tmp);
  8. stack.push(val);
  9. }else{
  10. // + - / *
  11. Integer val2 = stack.pop();
  12. Integer val1 = stack.pop();
  13. switch(tmp){
  14. case "+":
  15. Integer ret1 = val1+val2;
  16. stack.push(ret1);
  17. break;
  18. case "-":
  19. Integer ret2 = val1-val2;
  20. stack.push(ret2);
  21. break;
  22. case "*":
  23. Integer ret3 = val1*val2;
  24. stack.push(ret3);
  25. break;
  26. case "/":
  27. Integer ret4 = val1/val2;
  28. stack.push(ret4);
  29. break;
  30. }
  31. }
  32. }
  33. return stack.pop();
  34. }
  35. public boolean isOpearation(String s){
  36. if(s.equals("+") || s.equals("-") || s.equals("*") || s.equals("/")){
  37. return true;
  38. }
  39. return false;
  40. }
  41. }

3. 括号匹配 OJ链接

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

有效字符串需满足:

  1. 左括号必须用相同类型的右括号闭合。
  2. 左括号必须以正确的顺序闭合。
  3. 每个右括号都有一个对应的相同类型的左括号。

解题思路: 

  1. class Solution {
  2. public boolean isValid(String s) {
  3. Stack<Character> stack = new Stack<>();
  4. for(int i = 0; i< s.length(); i++){
  5. char ch = s.charAt(i);
  6. //1,左括号入栈
  7. if(ch == '(' || ch == '{' || ch == '['){
  8. stack.push(ch);
  9. }else{
  10. //2.遇到了右括号
  11. if(stack.empty()){
  12. return false;
  13. }else{
  14. //3.取栈顶元素的左括号看和当前右括号是否匹配
  15. char chL = stack.peek();
  16. if(chL == '(' && ch == ')' || chL == '[' && ch == ']'
  17. ||chL == '{' && ch == '}'){
  18. //4.证明当前一对括号是匹配的
  19. stack.pop();
  20. }else{
  21. //5,当前括号不匹配
  22. return false;
  23. }
  24. }
  25. }
  26. }
  27. return stack.empty();
  28. }
  29. }

4 出栈入栈次序匹配OJ链接 

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

解题思路:

  1. public boolean IsPopOrder (int[] pushV, int[] popV) {
  2. // write code here
  3. Stack<Integer> stack = new Stack<>();
  4. int j = 0;
  5. for(int i = 0; i<pushV.length;i++){
  6. stack.push(pushV[i]);
  7. while(j<popV.length && !stack.empty()
  8. && stack.peek() == popV[j]){
  9. stack.pop();
  10. j++;
  11. }
  12. }
  13. return stack.empty();
  14. }
  15. }

最小栈  OJ链接

题目:设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。

实现 MinStack 类:

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

 解题思路:

  1. class MinStack {
  2. Stack<Integer> stack;
  3. Stack<Integer> minstack;
  4. public MinStack() {
  5. stack = new Stack<>();
  6. minstack = new Stack<>();
  7. }
  8. public void push(int val) {
  9. stack.push(val);
  10. if(minstack.empty()){
  11. minstack.push(val);
  12. }else{
  13. Integer peekVal = minstack.peek();
  14. if(val<= peekVal){
  15. minstack.push(val);
  16. }
  17. }
  18. }
  19. public void pop() {
  20. if(stack.empty()){
  21. return;
  22. }
  23. int popVal = stack.pop();
  24. if(popVal == minstack.peek()){
  25. minstack.pop();
  26. }
  27. }
  28. public int top() {
  29. if(stack.empty()){
  30. return -1;
  31. }
  32. return stack.peek();
  33. }
  34. public int getMin() {
  35. if(minstack.empty()){
  36. return -1;
  37. }
  38. return minstack.peek();
  39. }
  40. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/570418
推荐阅读
相关标签
  

闽ICP备14008679号