第 5 章 栈(一)

简介: 第 5 章 栈

1、栈的基本介绍

1.1、栈的实际需求

  • 请计算表达式:[722-5+1-5+3-3] 的值
  • 请问: 计算机底层是如何运算得到结果的? 注意不是简单的把算式列出运算,因为我们看这个算式 7 * 2 * 2 - 5,但是计算机怎么理解这个算式的
  • 对计算机而言, 它接收到的就是一个字符串, 我们讨论的是这个问题:


1.2、栈的基本性质

1)栈的英文为(stack)

2)栈是一个先入后出(FILO-First In Last Out)的有序列表

3)栈(stack)是限制线性表中元素的插入和删除只能在线性表的同一端进行的一种特殊线性表。 允许插入和删除的一端, 为变化的一端, 称为栈顶(Top), 另一端为固定的一端, 称为栈底(Bottom)。

4)根据栈的定义可知, 最先放入栈中元素在栈底, 最后放入的元素在栈顶, 而删除元素刚好相反, 最后放入的元素最先删除, 最先放入的元素最后删除

图解方式说明出栈(pop)和入栈(push)的概念




1.3、栈的应用场景

子程序的调用: 在跳往子程序前, 会先将下个指令的地址存到堆栈中, 直到子程序执行完后再将地址取出, 以回到原来的程序中。

处理递归调用: 和子程序的调用类似, 只是除了储存下一个指令的地址外, 也将参数、 区域变量等数据存入栈中。

表达式的转换:[中缀表达式转后缀表达式]与求值(实际解决)。

二叉树的遍历。

图形的深度优先(depth 一 first)搜索法。




2、数组模拟栈

2.1、代码思路

maxSize :栈的大小(数组的大小)

arr :用来模拟栈的数组

top :指向当前栈顶元素,初始值为 -1 ,表示栈空

判断栈满:top == maxSize ,即已经到达数组最后一个位置

判断栈空:top == -1

入栈:arr[++top] = arr;

出栈:return arr[top–] ;




2.2、代码实现

  • 栈的定义
//定义一个 ArrayStack 表示栈
class ArrayStack {
 private int maxSize; // 栈的大小
 private int[] stack; // 数组,数组模拟栈,数据就放在该数组
 private int top = -1;// top表示栈顶,初始化为-1
 // 构造器
 public ArrayStack(int maxSize) {
  this.maxSize = maxSize;
  stack = new int[this.maxSize];
 }
 // 栈满
 public boolean isFull() {
  return top == maxSize - 1;
 }
 // 栈空
 public boolean isEmpty() {
  return top == -1;
 }
 // 入栈-push
 public void push(int value) {
  // 先判断栈是否满
  if (isFull()) {
   System.out.println("栈满");
   return;
  }
  top++;
  stack[top] = value;
 }
 // 出栈-pop, 将栈顶的数据返回
 public int pop() {
  // 先判断栈是否空
  if (isEmpty()) {
   // 抛出异常
   throw new RuntimeException("栈空,没有数据~");
  }
  int value = stack[top];
  top--;
  return value;
 }
 // 显示栈的情况[遍历栈], 遍历时,需要从栈顶开始显示数据
 public void list() {
  if (isEmpty()) {
   System.out.println("栈空,没有数据~~");
   return;
  }
  // 需要从栈顶开始显示数据
  for (int i = top; i >= 0; i--) {
   System.out.printf("stack[%d]=%d\n", i, stack[i]);
  }
 }
}


  • 测试代码
public static void main(String[] args) {
    // 测试一下ArrayStack 是否正确
    // 先创建一个ArrayStack对象->表示栈
    ArrayStack stack = new ArrayStack(4);
    String key = "";
    boolean loop = true; // 控制是否退出菜单
    Scanner scanner = new Scanner(System.in);
    while (loop) {
        System.out.println("show: 表示显示栈");
        System.out.println("exit: 退出程序");
        System.out.println("push: 表示添加数据到栈(入栈)");
        System.out.println("pop: 表示从栈取出数据(出栈)");
        System.out.println();
        System.out.println("请输入你的选择");
        key = scanner.next();
        switch (key) {
            case "show":
                stack.list();
                break;
            case "push":
                System.out.println("请输入一个数");
                int value = scanner.nextInt();
                stack.push(value);
                break;
            case "pop":
                try {
                    int res = stack.pop();
                    System.out.printf("出栈的数据是 %d\n", res);
                } catch (Exception e) {
                    // TODO: handle exception
                    System.out.println(e.getMessage());
                }
                break;
            case "exit":
                scanner.close();
                loop = false;
                break;
            default:
                break;
        }
    }
    System.out.println("程序退出~~~");
}
  • 程序运行结果
show: 表示显示栈
exit: 退出程序
push: 表示添加数据到栈(入栈)
pop: 表示从栈取出数据(出栈)
请输入你的选择
push
请输入一个数
1
show: 表示显示栈
exit: 退出程序
push: 表示添加数据到栈(入栈)
pop: 表示从栈取出数据(出栈)
请输入你的选择
push
请输入一个数
2
show: 表示显示栈
exit: 退出程序
push: 表示添加数据到栈(入栈)
pop: 表示从栈取出数据(出栈)
请输入你的选择
push
请输入一个数
3
show: 表示显示栈
exit: 退出程序
push: 表示添加数据到栈(入栈)
pop: 表示从栈取出数据(出栈)
请输入你的选择
push
请输入一个数
4
show: 表示显示栈
exit: 退出程序
push: 表示添加数据到栈(入栈)
pop: 表示从栈取出数据(出栈)
请输入你的选择
push
请输入一个数
5
栈满
show: 表示显示栈
exit: 退出程序
push: 表示添加数据到栈(入栈)
pop: 表示从栈取出数据(出栈)
请输入你的选择
show
stack[3]=4
stack[2]=3
stack[1]=2
stack[0]=1
show: 表示显示栈
exit: 退出程序
push: 表示添加数据到栈(入栈)
pop: 表示从栈取出数据(出栈)
请输入你的选择
pop
出栈的数据是 4
show: 表示显示栈
exit: 退出程序
push: 表示添加数据到栈(入栈)
pop: 表示从栈取出数据(出栈)
请输入你的选择
pop
出栈的数据是 3
show: 表示显示栈
exit: 退出程序
push: 表示添加数据到栈(入栈)
pop: 表示从栈取出数据(出栈)
请输入你的选择
pop
出栈的数据是 2
show: 表示显示栈
exit: 退出程序
push: 表示添加数据到栈(入栈)
pop: 表示从栈取出数据(出栈)
请输入你的选择
pop
出栈的数据是 1
show: 表示显示栈
exit: 退出程序
push: 表示添加数据到栈(入栈)
pop: 表示从栈取出数据(出栈)
请输入你的选择
pop
栈空,没有数据~
show: 表示显示栈
exit: 退出程序
push: 表示添加数据到栈(入栈)
pop: 表示从栈取出数据(出栈)
请输入你的选择


2.3、数组模拟栈全部代码

public class ArrayStackDemo {
 public static void main(String[] args) {
  // 测试一下ArrayStack 是否正确
  // 先创建一个ArrayStack对象->表示栈
  ArrayStack stack = new ArrayStack(4);
  String key = "";
  boolean loop = true; // 控制是否退出菜单
  Scanner scanner = new Scanner(System.in);
  while (loop) {
   System.out.println("show: 表示显示栈");
   System.out.println("exit: 退出程序");
   System.out.println("push: 表示添加数据到栈(入栈)");
   System.out.println("pop: 表示从栈取出数据(出栈)");
   System.out.println();
   System.out.println("请输入你的选择");
   key = scanner.next();
   switch (key) {
   case "show":
    stack.list();
    break;
   case "push":
    System.out.println("请输入一个数");
    int value = scanner.nextInt();
    stack.push(value);
    break;
   case "pop":
    try {
     int res = stack.pop();
     System.out.printf("出栈的数据是 %d\n", res);
    } catch (Exception e) {
     // TODO: handle exception
     System.out.println(e.getMessage());
    }
    break;
   case "exit":
    scanner.close();
    loop = false;
    break;
   default:
    break;
   }
  }
  System.out.println("程序退出~~~");
 }
}
//定义一个 ArrayStack 表示栈
class ArrayStack {
 private int maxSize; // 栈的大小
 private int[] stack; // 数组,数组模拟栈,数据就放在该数组
 private int top = -1;// top表示栈顶,初始化为-1
 // 构造器
 public ArrayStack(int maxSize) {
  this.maxSize = maxSize;
  stack = new int[this.maxSize];
 }
 // 栈满
 public boolean isFull() {
  return top == maxSize - 1;
 }
 // 栈空
 public boolean isEmpty() {
  return top == -1;
 }
 // 入栈-push
 public void push(int value) {
  // 先判断栈是否满
  if (isFull()) {
   System.out.println("栈满");
   return;
  }
  top++;
  stack[top] = value;
 }
 // 出栈-pop, 将栈顶的数据返回
 public int pop() {
  // 先判断栈是否空
  if (isEmpty()) {
   // 抛出异常
   throw new RuntimeException("栈空,没有数据~");
  }
  int value = stack[top];
  top--;
  return value;
 }
 // 显示栈的情况[遍历栈], 遍历时,需要从栈顶开始显示数据
 public void list() {
  if (isEmpty()) {
   System.out.println("栈空,没有数据~~");
   return;
  }
  // 需要从栈顶开始显示数据
  for (int i = top; i >= 0; i--) {
   System.out.printf("stack[%d]=%d\n", i, stack[i]);
  }
 }
}


2.4、课后练习

  • 使用链表模拟栈

3、栈实现综合计算器(中缀表达式)

3.1、代码思路

  • 栈分为两个栈:
  • 数栈(numStack):存储表达式中的数字
  • 符号栈(operStack):存储表达式中的符号
  • 扫描表达式(这里并没有考虑括号):
  • 对于数:扫描到数,则直接压入数栈
  • 对于运算符:扫描到运算符,分为如下几种情况:
  • 如果符号栈为空,则直接入栈
  • 如果符号栈不为空
  • 如果当前扫描到的运算符的优先级 <= 符号栈栈顶的运算符的优先级,说明上次的运算符优先级较高,先执行优先级高的运算
  • 从数栈中弹出两个数,根据符号栈栈顶的运算符进行运算(优先级高,就先算出来)
  • 然后将计算的结果压入栈中
  • 再将当前运算符压入符号栈
  • 如果当前扫描到的运算符的优先级 > 符号栈栈顶的运算符的优先级,说明上次的运算符优先级较低,直接压入符号栈
  • 何时停止循环?
  • 处理完表达式,退出循环
  • 即表达式下标(index)的值大于表达式(expression)的长度
  • 代码:index >= expression.length()
  • 表达式扫描完成:
  • 此时符号栈中的运算符优先级都相同
  • 从数栈中弹出两个数,再从符号栈中弹出一个运算符,进行运算,计算结果放回数栈中
  • 何时停止循环?符号栈为空则停止:operStack.isEmpty()
  • 表达式的值?符号栈为空时,数栈栈顶还有一个元素,这个元素的值就是表达式的值

举例:3+2*6-2

  • 首先
  • 将 3 压入数栈
  • 将 + 压入符号栈
  • 将 2 压入数栈

2

3   +

数栈 符号栈


  • 由于 * 优先级大于 + ,所以将 * 压入 符号栈,然后将 6 压入数栈

6

2   *

3   +

数栈 符号栈


  • 由于 - 优先级低于 * ,所以从数栈中弹出两个数(6 和 2),从符号栈中弹出一个运算符(*),进行运算,运算结果再压入数栈,然后将 - 压入符号栈

12   -

3   +

数栈 符号栈


  • 将 2 压入数栈,表达式处理完毕

2

12   -

3   +

数栈 符号栈


  • 重复此过程,直至符号栈为空:从数栈中弹出两个数,再从符号栈中弹出一个运算符,进行运算,计算结果放回数栈中

10

3   +

数栈 符号栈

13

数栈 符号栈


3.2、代码实现

  • 栈的定义:专为计算器而生的栈
  • 对于乘除法特别说明:由于栈先进后出的特点,num1 是运算符后面的数(减数、除数),num2 是运算符前的数(被减数、被除数),特别需要注意减法与除法的顺序
  • res = num2 - num1;
  • res = num2 / num1;
//先创建一个栈,直接使用前面创建好
//定义一个 CalcStack 表示栈, 需要扩展功能
class CalcStack {
 private int maxSize; // 栈的大小
 private int[] stack; // 数组,数组模拟栈,数据就放在该数组
 private int top = -1;// top表示栈顶,初始化为-1
 // 构造器
 public CalcStack(int maxSize) {
  this.maxSize = maxSize;
  stack = new int[this.maxSize];
 }
 // 增加一个方法,可以返回当前栈顶的值, 但是不是真正的pop
 public int peek() {
  return stack[top];
 }
 // 栈满
 public boolean isFull() {
  return top == maxSize - 1;
 }
 // 栈空
 public boolean isEmpty() {
  return top == -1;
 }
 // 入栈-push
 public void push(int value) {
  // 先判断栈是否满
  if (isFull()) {
   System.out.println("栈满");
   return;
  }
  top++;
  stack[top] = value;
 }
 // 出栈-pop, 将栈顶的数据返回
 public int pop() {
  // 先判断栈是否空
  if (isEmpty()) {
   // 抛出异常
   throw new RuntimeException("栈空,没有数据~");
  }
  int value = stack[top];
  top--;
  return value;
 }
 // 显示栈的情况[遍历栈], 遍历时,需要从栈顶开始显示数据
 public void list() {
  if (isEmpty()) {
   System.out.println("栈空,没有数据~~");
   return;
  }
  // 需要从栈顶开始显示数据
  for (int i = top; i >= 0; i--) {
   System.out.printf("stack[%d]=%d\n", i, stack[i]);
  }
 }
 // 返回运算符的优先级,优先级是程序员来确定, 优先级使用数字表示
 // 数字越大,则优先级就越高.
 public int priority(int oper) {
  if (oper == '*' || oper == '/') {
   return 1;
  } else if (oper == '+' || oper == '-') {
   return 0;
  } else {
   return -1; // 假定目前的表达式只有 +, - , * , /
  }
 }
 // 判断是不是一个运算符
 public boolean isOper(char val) {
  return val == '+' || val == '-' || val == '*' || val == '/';
 }
 // 计算方法
 public int cal(int num1, int num2, int oper) {
  int res = 0; // res 用于存放计算的结果
  switch (oper) {
  case '+':
   res = num1 + num2;
   break;
  case '-':
   res = num2 - num1;// 注意顺序
   break;
  case '*':
   res = num1 * num2;
   break;
  case '/':
   res = num2 / num1;
   break;
  default:
   break;
  }
  return res;
 }
}
  • 综合计算器代码:对多位数进行了判断,使得程序可处理多位数的运算
public static void main(String[] args) {
    // 根据前面老师思路,完成表达式的运算
    String expression = "7*2*2-5+1-5+3-4"; // 如何处理多位数的问题?
    // 创建两个栈,一个数栈,一个符号栈
    CalcStack numStack = new CalcStack(10);
    CalcStack operStack = new CalcStack(10);
    // 定义需要的相关变量
    int index = 0;// 用于扫描
    int num1 = 0;
    int num2 = 0;
    int oper = 0;
    int res = 0;
    char ch = ' '; // 将每次扫描得到char保存到ch
    String keepNum = ""; // 用于拼接 多位数
    // 开始while循环的扫描expression
    while (true) {
        // 依次得到expression 的每一个字符
        ch = expression.substring(index, index + 1).charAt(0);
        // 判断ch是什么,然后做相应的处理
        if (operStack.isOper(ch)) {// 如果是运算符
            // 判断当前的符号栈是否为空
            if (!operStack.isEmpty()) {
                // 如果符号栈有操作符,就进行比较,如果当前的操作符的优先级小于或者等于栈中的操作符,就需要从数栈中pop出两个数,
                // 在从符号栈中pop出一个符号,进行运算,将得到结果,入数栈,然后将当前的操作符入符号栈
                if (operStack.priority(ch) <= operStack.priority(operStack.peek())) {
                    num1 = numStack.pop();
                    num2 = numStack.pop();
                    oper = operStack.pop();
                    res = numStack.cal(num1, num2, oper);
                    // 把运算的结果如数栈
                    numStack.push(res);
                    // 然后将当前的操作符入符号栈
                    operStack.push(ch);
                } else {
                    // 如果当前的操作符的优先级大于栈中的操作符, 就直接入符号栈.
                    operStack.push(ch);
                }
            } else {
                // 如果为空直接入符号栈..
                operStack.push(ch); // 1 + 3
            }
        } else { // 如果是数,则直接入数栈
            // numStack.push(ch - 48); //? "1+3" '1' => 1
            // 分析思路
            // 1. 当处理多位数时,不能发现是一个数就立即入栈,因为他可能是多位数
            // 2. 在处理数,需要向expression的表达式的index 后再看一位,如果是数就进行扫描,如果是符号才入栈
            // 3. 因此我们需要定义一个变量 字符串,用于拼接
            // 处理多位数
            keepNum += ch;
            // 如果ch已经是expression的最后一位,就直接入栈
            if (index == expression.length() - 1) {
                numStack.push(Integer.parseInt(keepNum));
            } else {
                // 判断下一个字符是不是数字,如果是数字,就继续扫描,如果是运算符,则入栈
                // 注意是看后一位,不是index++
                if (operStack.isOper(expression.substring(index + 1, index + 2).charAt(0))) {
                    // 如果后一位是运算符,则入栈 keepNum = "1" 或者 "123"
                    numStack.push(Integer.parseInt(keepNum));
                    // 重要的!!!!!!, keepNum清空
                    keepNum = "";
                }
            }
        }
        // 让index + 1, 并判断是否扫描到expression最后.
        index++;
        if (index >= expression.length()) {
            break;
        }
    }
    // 当表达式扫描完毕,就顺序的从 数栈和符号栈中pop出相应的数和符号,并运行.
    while (true) {
        // 如果符号栈为空,则计算到最后的结果, 数栈中只有一个数字【结果】
        if (operStack.isEmpty()) {
            break;
        }
        num1 = numStack.pop();
        num2 = numStack.pop();
        oper = operStack.pop();
        res = numStack.cal(num1, num2, oper);
        numStack.push(res);// 入栈
    }
    // 将数栈的最后数,pop出,就是结果
    res = numStack.pop();
    System.out.printf("表达式 %s = %d", expression, res);
}
  • 程序运行结果
表达式 7*2*2-5+1-5+3-4 = 18

3.3、综合计算器全部代码

public class Calculator {
 public static void main(String[] args) {
  // 根据前面老师思路,完成表达式的运算
  String expression = "7*2*2-5+1-5+3-4"; // 如何处理多位数的问题?
  // 创建两个栈,一个数栈,一个符号栈
  CalcStack numStack = new CalcStack(10);
  CalcStack operStack = new CalcStack(10);
  // 定义需要的相关变量
  int index = 0;// 用于扫描
  int num1 = 0;
  int num2 = 0;
  int oper = 0;
  int res = 0;
  char ch = ' '; // 将每次扫描得到char保存到ch
  String keepNum = ""; // 用于拼接 多位数
  // 开始while循环的扫描expression
  while (true) {
   // 依次得到expression 的每一个字符
   ch = expression.substring(index, index + 1).charAt(0);
   // 判断ch是什么,然后做相应的处理
   if (operStack.isOper(ch)) {// 如果是运算符
    // 判断当前的符号栈是否为空
    if (!operStack.isEmpty()) {
     // 如果符号栈有操作符,就进行比较,如果当前的操作符的优先级小于或者等于栈中的操作符,就需要从数栈中pop出两个数,
     // 在从符号栈中pop出一个符号,进行运算,将得到结果,入数栈,然后将当前的操作符入符号栈
     if (operStack.priority(ch) <= operStack.priority(operStack.peek())) {
      num1 = numStack.pop();
      num2 = numStack.pop();
      oper = operStack.pop();
      res = numStack.cal(num1, num2, oper);
      // 把运算的结果如数栈
      numStack.push(res);
      // 然后将当前的操作符入符号栈
      operStack.push(ch);
     } else {
      // 如果当前的操作符的优先级大于栈中的操作符, 就直接入符号栈.
      operStack.push(ch);
     }
    } else {
     // 如果为空直接入符号栈..
     operStack.push(ch); // 1 + 3
    }
   } else { // 如果是数,则直接入数栈
    // numStack.push(ch - 48); //? "1+3" '1' => 1
    // 分析思路
    // 1. 当处理多位数时,不能发现是一个数就立即入栈,因为他可能是多位数
    // 2. 在处理数,需要向expression的表达式的index 后再看一位,如果是数就进行扫描,如果是符号才入栈
    // 3. 因此我们需要定义一个变量 字符串,用于拼接
    // 处理多位数
    keepNum += ch;
    // 如果ch已经是expression的最后一位,就直接入栈
    if (index == expression.length() - 1) {
     numStack.push(Integer.parseInt(keepNum));
    } else {
     // 判断下一个字符是不是数字,如果是数字,就继续扫描,如果是运算符,则入栈
     // 注意是看后一位,不是index++
     if (operStack.isOper(expression.substring(index + 1, index + 2).charAt(0))) {
      // 如果后一位是运算符,则入栈 keepNum = "1" 或者 "123"
      numStack.push(Integer.parseInt(keepNum));
      // 重要的!!!!!!, keepNum清空
      keepNum = "";
     }
    }
   }
   // 让index + 1, 并判断是否扫描到expression最后.
   index++;
   if (index >= expression.length()) {
    break;
   }
  }
  // 当表达式扫描完毕,就顺序的从 数栈和符号栈中pop出相应的数和符号,并运行.
  while (true) {
   // 如果符号栈为空,则计算到最后的结果, 数栈中只有一个数字【结果】
   if (operStack.isEmpty()) {
    break;
   }
   num1 = numStack.pop();
   num2 = numStack.pop();
   oper = operStack.pop();
   res = numStack.cal(num1, num2, oper);
   numStack.push(res);// 入栈
  }
  // 将数栈的最后数,pop出,就是结果
  res = numStack.pop();
  System.out.printf("表达式 %s = %d", expression, res);
 }
}
//先创建一个栈,直接使用前面创建好
//定义一个 CalcStack 表示栈, 需要扩展功能
class CalcStack {
 private int maxSize; // 栈的大小
 private int[] stack; // 数组,数组模拟栈,数据就放在该数组
 private int top = -1;// top表示栈顶,初始化为-1
 // 构造器
 public CalcStack(int maxSize) {
  this.maxSize = maxSize;
  stack = new int[this.maxSize];
 }
 // 增加一个方法,可以返回当前栈顶的值, 但是不是真正的pop
 public int peek() {
  return stack[top];
 }
 // 栈满
 public boolean isFull() {
  return top == maxSize - 1;
 }
 // 栈空
 public boolean isEmpty() {
  return top == -1;
 }
 // 入栈-push
 public void push(int value) {
  // 先判断栈是否满
  if (isFull()) {
   System.out.println("栈满");
   return;
  }
  top++;
  stack[top] = value;
 }
 // 出栈-pop, 将栈顶的数据返回
 public int pop() {
  // 先判断栈是否空
  if (isEmpty()) {
   // 抛出异常
   throw new RuntimeException("栈空,没有数据~");
  }
  int value = stack[top];
  top--;
  return value;
 }
 // 显示栈的情况[遍历栈], 遍历时,需要从栈顶开始显示数据
 public void list() {
  if (isEmpty()) {
   System.out.println("栈空,没有数据~~");
   return;
  }
  // 需要从栈顶开始显示数据
  for (int i = top; i >= 0; i--) {
   System.out.printf("stack[%d]=%d\n", i, stack[i]);
  }
 }
 // 返回运算符的优先级,优先级是程序员来确定, 优先级使用数字表示
 // 数字越大,则优先级就越高.
 public int priority(int oper) {
  if (oper == '*' || oper == '/') {
   return 1;
  } else if (oper == '+' || oper == '-') {
   return 0;
  } else {
   return -1; // 假定目前的表达式只有 +, - , * , /
  }
 }
 // 判断是不是一个运算符
 public boolean isOper(char val) {
  return val == '+' || val == '-' || val == '*' || val == '/';
 }
 // 计算方法
 public int cal(int num1, int num2, int oper) {
  int res = 0; // res 用于存放计算的结果
  switch (oper) {
  case '+':
   res = num1 + num2;
   break;
  case '-':
   res = num2 - num1;// 注意顺序
   break;
  case '*':
   res = num1 * num2;
   break;
  case '/':
   res = num2 / num1;
   break;
  default:
   break;
  }
  return res;
 }
}

3.4、课后练习

  • 加入小括号的判断:小括号内的运算需要优先执行,也即小括号的优先级最高
  • 我的代码思路如下:
  • 但凡遇到左括号,直接入符号栈,之后的操作和之前的一样
  • 直至遇到右括号,此时可以依次将符号栈中的符号弹出,与数栈中的数做运算
  • 直至符号栈弹出左括号为止,此时,括号内的运算已执行完毕
目录
相关文章
|
6天前
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
65 9
|
1月前
|
存储 算法 搜索推荐
探索常见数据结构:数组、链表、栈、队列、树和图
探索常见数据结构:数组、链表、栈、队列、树和图
88 64
|
2天前
|
存储 JavaScript 前端开发
执行上下文和执行栈
执行上下文是JavaScript运行代码时的环境,每个执行上下文都有自己的变量对象、作用域链和this值。执行栈用于管理函数调用,每当调用一个函数,就会在栈中添加一个新的执行上下文。
|
4天前
|
存储
系统调用处理程序在内核栈中保存了哪些上下文信息?
【10月更文挑战第29天】系统调用处理程序在内核栈中保存的这些上下文信息对于保证系统调用的正确执行和用户程序的正常恢复至关重要。通过准确地保存和恢复这些信息,操作系统能够实现用户模式和内核模式之间的无缝切换,为用户程序提供稳定、可靠的系统服务。
26 4
|
28天前
|
算法 程序员 索引
数据结构与算法学习七:栈、数组模拟栈、单链表模拟栈、栈应用实例 实现 综合计算器
栈的基本概念、应用场景以及如何使用数组和单链表模拟栈,并展示了如何利用栈和中缀表达式实现一个综合计算器。
26 1
数据结构与算法学习七:栈、数组模拟栈、单链表模拟栈、栈应用实例 实现 综合计算器
|
8天前
|
算法 安全 NoSQL
2024重生之回溯数据结构与算法系列学习之栈和队列精题汇总(10)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构王道第3章之IKUN和I原达人之数据结构与算法系列学习栈与队列精题详解、数据结构、C++、排序算法、java、动态规划你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
|
27天前
初步认识栈和队列
初步认识栈和队列
57 10
|
22天前
数据结构(栈与列队)
数据结构(栈与列队)
16 1
|
28天前
|
算法
数据结构与算法二:栈、前缀、中缀、后缀表达式、中缀表达式转换为后缀表达式
这篇文章讲解了栈的基本概念及其应用,并详细介绍了中缀表达式转换为后缀表达式的算法和实现步骤。
41 3
|
26天前
|
存储 JavaScript 前端开发
为什么基础数据类型存放在栈中,而引用数据类型存放在堆中?
为什么基础数据类型存放在栈中,而引用数据类型存放在堆中?
62 1