数据结构 | 栈的中缀表达式求值

这篇具有很好参考价值的文章主要介绍了数据结构 | 栈的中缀表达式求值。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

什么是栈?

栈的基本操作

入栈操作

出栈操作

取栈顶元素

中缀表达式求值

实现思路

具体代码


什么是栈?

栈是一种线性数据结构,具有“先进后出”(Last In First Out, LIFO)的特点。它可以看作是一种受限的线性表,只能在表的一端进行插入和删除操作,这一端被称为栈顶,另一端被称为栈底。不含任何元素的栈称为空栈。

利用栈实现一个中缀表达式的求值;,数据结构

                      栈的基本操作包括:入栈、出栈、取栈顶元素等。

栈的基本操作

  1. 理解栈的基本原理和操作;
  2. 掌握栈在表达式求值中的应用。

入栈操作

利用栈实现一个中缀表达式的求值;,数据结构

出栈操作

利用栈实现一个中缀表达式的求值;,数据结构

取栈顶元素

利用栈实现一个中缀表达式的求值;,数据结构

中缀表达式求值

中缀表达式是最常见的表达式表示方式,其表示形式为“操作数1 操作符 操作数2”。例如:

3+4

同样表示加法运算,参数分别为3和4,其结果为7。

对于表达式求值,我们通常使用中缀表达式,需要转换为前缀或后缀表达式。转换完成后,可以直接使用栈来求解表达式的值。

实现思路

中缀表达式求值比较复杂,需要考虑运算符的优先级以及括号的影响。因此,我们一般使用栈来实现算法。

具体实现过程如下:

  1. 初始化两个栈:运算符栈s1,存储中间结果的栈s2;
  2. 从左至右扫描中缀表达式;
  3. 遇到操作数时,将其压入s2;
  4. 遇到运算符时,比较其与s1栈顶运算符的优先级:
    1. 如果s1为空,或栈顶运算符为左括号“(”,则直接将此运算符入栈;
    2. 否则,若优先级比栈顶运算符的优先级高,则将运算符压入s1;
    3. 否则,将s1栈顶的运算符弹出并压入到s2中,再次转到步骤4-1与s1中新的栈顶运算符相比较;
  5. 遇到括号时:
    1. 如果是左括号“(”,则直接压入s1;
    2. 如果是右括号“)”,则依次弹出s1栈顶的运算符,并压入s2,直到遇到左括号为止,此时将这一对括号丢弃;
    3. 重复步骤2-5,直到表达式的最右边;
    4. 将s1中剩余的运算符依次弹出并压入s2;
    5. 依次弹出s2中的元素计算结果。

我们将使用C语言来实现栈的中缀表达式求值功能。具体步骤如下:文章来源地址https://www.toymoban.com/news/detail-786791.html

  1. 定义栈结构体和相关操作函数(如初始化、入栈、出栈、取栈顶元素等);
  2. 定义字符类型的栈用于存储运算符,定义浮点数类型的栈用于存储操作数和中间结果;
  3. 实现后缀表达式求值函数,使用上述算法;
  4. 编写主函数,测试中缀表达式求值函数。

具体代码

#include <stdio.h>
#include <stdlib.h>

typedef struct Node {
    int data;
    struct Node *next;
} Node;

typedef struct {
    Node *top;
} Stack;

int is_operator(char ch) {
    return (ch == '+' || ch == '-' || ch == '*' || ch == '/');
}

int priority(char op) {
    switch (op) {
        case '+':
        case '-':
            return 1;
        case '*':
        case '/':
            return 2;
        default:
            return 0;
    }
}

int calculate(int a, char op, int b) {
    switch (op) {
        case '+':
            return a + b;
        case '-':
            return a - b;
        case '*':
            return a * b;
        case '/':
            return a / b;
        default:
            exit(1);
    }
}

Stack *create_stack() {   // 创建空栈
    Stack *stack = (Stack *)malloc(sizeof(Stack));
    stack->top = NULL;
    return stack;
}

void push(Stack *stack, int data) {   // 入栈操作
    Node *node = (Node *)malloc(sizeof(Node));
    node->data = data;
    node->next = stack->top;
    stack->top = node;
}

int pop(Stack *stack) {   // 出栈操作
    if (stack->top == NULL) {
        return -1;   // 如果栈为空,则返回-1
    }
    Node *node = stack->top;
    int data = node->data;
    stack->top = node->next;
    free(node);
    return data;
}

int top(Stack *stack) {   // 返回栈顶元素
    if (stack->top == NULL) {
        return -1;   // 如果栈为空,则返回-1
    }
    return stack->top->data;
}

/**
 * 计算表达式结果的函数。
 *
 * @param expression 表达式字符串
 * @return 表达式的计算结果
 */
int evaluate_expression(char *expression) {
    Stack *s1 = create_stack();   // 操作数栈,用于存储操作数
    Stack *s2 = create_stack();   // 操作符栈,用于存储操作符

    for (int i = 0; expression[i] != '\0'; i++) {
        if (is_operator(expression[i])) {   // 如果当前字符为操作符
            while (s2->top != NULL && priority(top(s2)) >= priority(expression[i])) {
                // 如果操作符栈不为空,并且栈顶操作符的优先级大于等于当前操作符的优先级
                int b = pop(s1);    // 出栈一个操作数作为运算的右操作数
                int a = pop(s1);    // 再出栈一个操作数作为运算的左操作数
                char op = pop(s2);  // 出栈一个操作符
                int result = calculate(a, op, b);   // 计算两个操作数和操作符的结果
                push(s1, result);   // 将计算结果入栈到操作数栈中
            }
            push(s2, expression[i]);  // 当前操作符入栈到操作符栈中
        } else if (expression[i] == '(') { // 如果当前字符为左括号
            push(s2, expression[i]);    // 入栈到操作符栈中
        } else if (expression[i] == ')') { // 如果当前字符为右括号
            while (top(s2) != '(') {    // 循环执行直到遇到左括号
                int b = pop(s1);    // 出栈一个操作数作为运算的右操作数
                int a = pop(s1);    // 再出栈一个操作数作为运算的左操作数
                char op = pop(s2);  // 出栈一个操作符
                int result = calculate(a, op, b);   // 计算两个操作数和操作符的结果
                push(s1, result);   // 将计算结果入栈到操作数栈中
            }
            pop(s2);    // 弹出左括号
        } else {    // 如果当前字符为数字
            int num = expression[i] - '0';  // 将当前字符转换成数字
            while (expression[i + 1] >= '0' && expression[i + 1] <= '9') {
                // 如果下一个字符也是数字,则将其合并到一起
                num = num * 10 + expression[++i] - '0';
            }
            push(s1, num);  // 将数字入栈到操作数栈中
        }
    }

    // 处理剩余的操作符
    while (s2->top != NULL) {
        int b = pop(s1);    // 出栈一个操作数作为运算的右操作数
        int a = pop(s1);    // 再出栈一个操作数作为运算的左操作数
        char op = pop(s2);  // 出栈一个操作符
        int result = calculate(a, op, b);   // 计算两个操作数和操作符的结果
        push(s1, result);   // 将计算结果入栈到操作数栈中
    }
 
    return pop(s1); // 返回最终的计算结果
}


int main() {
    char expression[100];
    printf("请输入中缀表达式:");
    scanf("%s", expression);
    int result = evaluate_expression(expression);
    printf("计算结果:%d\n", result);
    return 0;
}

到了这里,关于数据结构 | 栈的中缀表达式求值的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 数据结构——前缀、中缀、后缀表达式实现和转换(Java)

    1.7.1 概念 它们都是对表达式的记法,因此也被称为前缀记法、中缀记法和后缀记法。它们之间的区别在于 运算符相对与操作数的位置 不同 前缀 表达式的运算符位于与其相关的 操作数之前 ;中缀和后缀同理。 平时我们 日常使用 并最为熟悉的就是中缀表达式。如: 1 + 2 *

    2024年02月05日
    浏览(55)
  • 【尚硅谷】数据结构和算法——前缀、中缀、后缀表达式规则

    跟着B站的尚硅谷学习数据结构与算法,语言为java,目前是第七个代码内容——前缀、中缀、后缀表达式 课程传送门:尚硅谷——前缀、中缀、后缀表达式 1)前缀表达式又称波兰式, 前缀表达式 的运算符位于操作符之前。 2)举例说明:(3+4)*5-6 对应的前缀表达式就是 - *

    2024年02月03日
    浏览(60)
  • 数据结构与算法-(7)---栈的应用-(4)后缀表达式求值

    🌈write in front🌈 🧸大家好,我是Aileen🧸.希望你看完之后,能对你有所帮助,不足请指正!共同学习交流. 🆔本文由Aileen_0v0🧸 原创 CSDN首发🐒 如需转载还请通知⚠️ 📝个人主页:Aileen_0v0🧸—CSDN博客 🎁欢迎各位→点赞👍 + 收藏⭐️ + 留言📝​ 📣系列专栏:Aileen_0v0🧸

    2024年02月07日
    浏览(52)
  • 中缀表达式求值(栈的应用)

    AcWing算法基础课-3302.表达式求值 给定一个表达式,其中运算符仅包含 +,-,*,/ (加 减 乘 整除),可能包含括号,请你求出表达式的最终值。 注意: 数据保证给定的表达式合法。 题目保证符号 - 只作为减号出现,不会作为负号出现,例如, -1+2 , (2+2)*(-(1+1)+2) 之类表达式均不

    2024年02月05日
    浏览(55)
  • 栈的数据结构完成表达式(5*10+2-7+5)/10+5的计算

    栈(Stack)是一种线性数据结构,具有后进先出(LIFO)的特性。它可以理解为一种类似于抽屉的容器,只能在顶部进行插入和删除操作,其他位置不可访问。栈的基本操作包括入栈(push)和出栈(pop),其中入栈将元素放入栈顶,出栈将栈顶元素移出。 栈在计算机科学和软

    2024年02月09日
    浏览(37)
  • 北京林业大学数据结构实验二 基于栈的算术表达式求值算法

    参见课本P75 例3.3

    2024年02月06日
    浏览(48)
  • Java LeetCode篇-深入了解关于栈的经典解法(栈实现:中缀表达式转后缀)

    🔥博客主页: 【 小扳_-CSDN博客】 ❤感谢大家点赞👍收藏⭐评论✍     文章目录         1.0 中缀表达式转后缀说明         1.1 实现中缀表达式转后缀思路         2.0 逆波兰表达式求值         2.1 实现逆波兰表达式求值思路         3.0 有效的括号         3.1 实现有

    2024年02月04日
    浏览(60)
  • 【 第1关:基于栈的中缀算术表达式求值】【编程题实训-栈】【头歌】【bjfu-240】

    本关任务:输入一个中缀算术表达式,求解表达式的值。运算符包括+、-、*、/、(、)、=,参加运算的数为double类型且为正数。(要求:直接针对中缀算术表达式进行计算,不能转换为后缀或前缀表达式再进行计算,只考虑二元运算即可。) 输入 多组数据,每组数据一行,对

    2024年02月06日
    浏览(53)
  • 【数据结构】超详细讲解:算术表达式转化为后缀表达式、前缀表达式、表达式树的构建

    作者: 努力学习的大一在校计算机专业学生,热爱学习和创作。目前在学习和分享:算法、数据结构、Java等相关知识。 博主主页: @是瑶瑶子啦 所属专栏: 【数据结构】:该专栏专注于数据结构知识,持续更新,每一篇内容优质,浅显易懂,不失深度! 近期目标: 写好专栏

    2024年02月08日
    浏览(53)
  • 数据结构之表达式求值

     前言 运用堆栈解决表达式的求值,代码思路为: 1.定义两个栈,一个char类型的栈用于存放运算符(ysf)一个int类型的栈用于存放操作数(czs) 如一个表达式3+6*9,将“+”,“*”入ysf栈,将“3”“6”“9”入czs栈 2.运用getchar进行数据的录入,如果接收的是运算符,将其插入到运

    2024年04月29日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包