C语言实现逆波兰式实例

C语言实现逆波兰式实例

逆波兰式是一种数学表达式表示法,也称为后缀表达式。与常见的表达式表示法不同,逆波兰式将操作数放在操作符之前,能够方便地使用栈等数据结构进行表达式的求解。在C语言中实现逆波兰式求值可以采用栈的数据结构进行实现。本文将介绍基于栈的C语言实现逆波兰式的完整攻略。

逆波兰式的基本原理

逆波兰式可以通过以下步骤进行转换:

  1. 从左到右扫描中缀表达式。
  2. 遇到操作符时,将其压入栈中。
  3. 遇到操作数时,将其输出。
  4. 遇到右括号时,将操作符弹出并输出,直到遇到左括号。
  5. 如果遇到其他操作符,判断其与栈顶操作符的优先级关系,如果栈顶操作符的优先级大于该操作符,则将栈顶操作符弹出并输出,再将该操作符压入栈中。
  6. 重复步骤2-5,直到将中缀表达式转换为后缀表达式。

C语言实现逆波兰式的基本步骤

  1. 定义一个栈结构体,包含栈顶指针以及栈的大小等信息。
  2. 定义一个函数,用于将中缀表达式转换为后缀表达式,其中使用栈来维护操作符。
  3. 定义一个函数,用于计算后缀表达式的值,其中使用栈来维护操作数。

示例说明1:将中缀表达式转换为后缀表达式

以下为一个简单的例子:

#include <stdio.h>

#define MAXSIZE 100

typedef enum {
    OP_PLUS = '+',
    OP_MINUS = '-',
    OP_MULTIPLY = '*',
    OP_DIVIDE = '/',
    OP_LEFT_PARENTHESES = '(',
    OP_RIGHT_PARENTHESES = ')',
    OP_END = '\0'
} operator;

typedef struct {
    operator* top;
    operator* stack;
    int size;
} operator_stack;

void operator_push(operator_stack* stack, operator op) {
    if (stack->top - stack->stack >= stack->size) {
        printf("stack is full\n");
        return;
    }
    *(++stack->top) = op;
}

operator operator_pop(operator_stack* stack) {
    if (stack->top == stack->stack) {
        printf("stack is empty\n");
        return OP_END;
    }
    return *(stack->top--);
}

operator operator_top(operator_stack* stack) {
    if (stack->top == stack->stack) {
        printf("stack is empty\n");
        return OP_END;
    }
    return *(stack->top);
}

operator_stack* operator_stack_create(int size) {
    operator_stack* stack = (operator_stack*) malloc(sizeof(operator_stack));
    stack->top = stack->stack - 1;
    stack->stack = (operator*) malloc(sizeof(operator) * size);
    stack->size = size;
    return stack;
}

void operator_stack_destroy(operator_stack* stack) {
    free(stack->stack);
    stack->stack = NULL;
    stack->top = NULL;
    stack->size = 0;
    free(stack);
}

int is_number(char ch) {
    return ch >= '0' && ch <= '9';
}

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

int is_higher_priority(operator op1, operator op2) {
    switch (op1) {
        case OP_DIVIDE:
        case OP_MULTIPLY:
            return op2 == OP_PLUS || op2 == OP_MINUS;
        case OP_PLUS:
        case OP_MINUS:
            return op2 == OP_LEFT_PARENTHESES;
        case OP_LEFT_PARENTHESES:
        default:
            return 0;
    }
}

void infix_to_postfix(char* infix, char* postfix, int size) {
    operator_stack* stack = operator_stack_create(size);
    operator_push(stack, OP_LEFT_PARENTHESES);
    int i = 0;
    int j = 0;
    while (infix[i] != '\0') {
        char ch = infix[i++];
        if (is_number(ch)) {
            postfix[j++] = ch;
        } else if (is_operator(ch)) {
            if (ch == OP_LEFT_PARENTHESES) {
                operator_push(stack, ch);
            } else if (ch == OP_RIGHT_PARENTHESES) {
                operator top = operator_pop(stack);
                while (top != OP_LEFT_PARENTHESES) {
                    postfix[j++] = top;
                    top = operator_pop(stack);
                }
            } else {
                operator top = operator_top(stack);
                while (is_higher_priority(top, ch)) {
                    postfix[j++] = operator_pop(stack);
                    top = operator_top(stack);
                }
                operator_push(stack, ch);
            }
        } else {
            printf("invalid character: %c\n", ch);
        }
    }
    while (stack->top != stack->stack) {
        postfix[j++] = operator_pop(stack);
    }
    postfix[j] = '\0';
    operator_stack_destroy(stack);
}

int main() {
    char infix[MAXSIZE] = "3+4*5/(6+7)-8";
    char postfix[MAXSIZE];
    infix_to_postfix(infix, postfix, MAXSIZE);
    printf("infix: %s\npostfix: %s\n", infix, postfix);
    return 0;
}

在上面的示例代码中,我们定义了一个操作符栈来维护中缀表达式转换为后缀表达式的过程。其中operator_push、operator_pop和operator_top函数是操作栈的基本函数。is_higher_priority函数用来判断两个操作符的优先级。infix_to_postfix函数用来将中缀表达式转换为后缀表达式。在实际处理过程中,我们通过扫描中缀表达式中每一个字符,然后进行相应的操作。

示例说明2:计算后缀表达式的值

以下为一个简单的例子:

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

#define MAXSIZE 100

typedef enum {
    OP_PLUS = '+',
    OP_MINUS = '-',
    OP_MULTIPLY = '*',
    OP_DIVIDE = '/',
    OP_LEFT_PARENTHESES = '(',
    OP_RIGHT_PARENTHESES = ')',
    OP_END = '\0'
} operator;

typedef struct {
    int* top;
    int* stack;
    int size;
} integer_stack;

void integer_push(integer_stack* stack, int value) {
    if (stack->top - stack->stack >= stack->size) {
        printf("stack is full\n");
        return;
    }
    *(++stack->top) = value;
}

int integer_pop(integer_stack* stack) {
    if (stack->top == stack->stack) {
        printf("stack is empty\n");
        return 0;
    }
    return *(stack->top--);
}

int integer_top(integer_stack* stack) {
    if (stack->top == stack->stack) {
        printf("stack is empty\n");
        return 0;
    }
    return *(stack->top);
}

integer_stack* integer_stack_create(int size) {
    integer_stack* stack = (integer_stack*) malloc(sizeof(integer_stack));
    stack->top = stack->stack - 1;
    stack->stack = (int*) malloc(sizeof(int) * size);
    stack->size = size;
    return stack;
}

void integer_stack_destroy(integer_stack* stack) {
    free(stack->stack);
    stack->stack = NULL;
    stack->top = NULL;
    stack->size = 0;
    free(stack);
}

int is_number(char ch) {
    return ch >= '0' && ch <= '9';
}

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

int apply_operator(int left, int right, operator op) {
    switch (op) {
        case OP_PLUS:
            return left + right;
        case OP_MINUS:
            return left - right;
        case OP_MULTIPLY:
            return left * right;
        case OP_DIVIDE:
            return left / right;
        default:
            printf("invalid operator\n");
            return 0;
    }
}

int evaluate_postfix(char* postfix) {
    integer_stack* stack = integer_stack_create(strlen(postfix) + 1);
    int i = 0;
    while (postfix[i] != '\0') {
        char ch = postfix[i++];
        if (is_number(ch)) {
            integer_push(stack, ch - '0');
        } else if (is_operator(ch)) {
            int right = integer_pop(stack);
            int left = integer_pop(stack);
            integer_push(stack, apply_operator(left, right, ch));
        } else {
            printf("invalid character: %c\n", ch);
        }
    }
    int result = integer_pop(stack);
    integer_stack_destroy(stack);
    return result;
}

int main() {
    char postfix[MAXSIZE] = "345*67+/8-";
    int result = evaluate_postfix(postfix);
    printf("postfix: %s\nresult: %d\n", postfix, result);
    return 0;
}

在上面的示例代码中,我们定义了一个整数栈来维护后缀表达式求值的过程。其中integer_push、integer_pop和integer_top函数是操作栈的基本函数。apply_operator函数用来计算两个操作数的运算结果。evaluate_postfix函数用来计算后缀表达式的值。在实际处理过程中,我们通过扫描后缀表达式中每一个字符,然后进行相应的操作。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C语言实现逆波兰式实例 - Python技术站

(0)
上一篇 2023年5月23日
下一篇 2023年5月23日

相关文章

  • 深入理解Spring注解@Async解决异步调用问题

    下面我来详细讲解如何深入理解Spring注解@Async解决异步调用问题。 什么是@Async注解 Spring框架提供了@Async注解,该注解用于标记方法,表示该方法是异步的。当被标记的方法被调用时,它会在另外一个线程中运行,而不是阻塞主调线程。@Async注解使用在Spring中非常普遍,特别是在需要执行一些耗时的任务时,例如发送电子邮件、生成报告、下…

    C 2023年5月23日
    00
  • C语言算法练习之折半查找的实现

    C语言算法练习之折半查找的实现 什么是折半查找 折半查找(也称二分查找)是一种在有序数组中查找指定元素的查找算法,时间复杂度为O(logn)。 实现步骤 在实现折半查找前,需要明确以下几个步骤: 确定查找区间范围; 计算查找区间的中间位置; 比较中间位置和目标值; 不断缩小查找范围,直到找到目标值或者查找区间为空。 下面我们来一步步实现。 定义函数 首先需要…

    C 2023年5月22日
    00
  • 学习C++编程的必备软件

    下面我将为您详细讲解“学习C++编程的必备软件”的完整攻略。 学习C++编程的必备软件 1. C++编译器 C++编译器是你学习编程时必备的工具之一。编译器负责将写好的C++程序翻译成机器可以理解的语言,让计算机可以运行它。以下是几个常用的C++编译器: Visual Studio:Visual Studio是一个非常强大的开发环境,附带了C++编译器和许多…

    C 2023年5月23日
    00
  • Recommended C Style and Coding Standards中文翻译版

    首先,需要明确“Recommended C Style and Coding Standards”是一份由美国国防部发布的规范文档,旨在规范C语言程序的编写。该文档包含了C语言编程所需的规范、风格、注释、命名、代码布局和格式等方面的建议。如何应用该文档,建立自己的编程风格呢? 以下是应用“Recommended C Style and Coding Stan…

    C 2023年5月22日
    00
  • mysql中取出json字段的小技巧

    对于“mysql中取出json字段的小技巧”,可以进行如下讲解: 1. 确保MySQL版本支持JSON数据类型 在MySQL 5.7及以上的版本中,才支持JSON数据类型,如果你的MySQL版本过低,需要进行升级。可以通过如下命令查看MySQL版本: SELECT VERSION(); 如果版本太低,可以参考MySQL官方文档进行升级。升级完成后,可以在表中…

    C 2023年5月23日
    00
  • C语言利用cJSON解析JSON格式全过程

    当我们需要获取某个Web API的数据时,一般情况下会返回JSON格式的数据。如何使用C语言来解析这些JSON数据呢?这时候,就可以使用cJSON开源库。 cJSON是一款轻量级、快速的C语言JSON解析器。它使用简单,只需要包含一个头文件”cJSON.h”,并将相关代码文件加入到项目中即可。下面将详细讲解cJSON解析JSON格式的全过程。 第一步:安装c…

    C 2023年5月22日
    00
  • c++实现值机系统

    C++实现值机系统攻略 1. 确定需求 在实现值机系统之前,我们需要确定需求,具体包括以下几个方面: 登记航班信息,包括航班号、起飞时间、到达时间、起飞机场、到达机场、预计飞行时间等。 登记乘客信息,包括乘客姓名、证件类型、证件号码、航班号、座位号等。 实现在线值机功能,可以选择座位、打印登机牌等。 实现退改签功能,可以修改预定信息或取消预定。 实现管理员功…

    C 2023年5月23日
    00
  • C语言函数指针数组实现计算器功能

    要实现一个简单的计算器,我们可以利用函数指针数组来实现。具体的代码实现,可以如下: 1. 定义函数指针 首先,我们需要定义四个函数,分别实现加、减、乘、除操作。然后,我们定义一个函数指针数组,用来存储这四个函数。 // 定义加、减、乘、除四个函数 int add(int a, int b) { return a+b; } int sub(int a, int…

    C 2023年5月24日
    00
合作推广
合作推广
分享本页
返回顶部