栈的应用-四则运算求值

栈的应用-四则运算求值

后缀表达式(逆波兰)

从左到右遍历表达式,若遇到数字则直接输出。若遇到符号,则与符号栈中的栈顶元素进行对比(乘除优先于加减),若优先级低于栈顶元素或为右括号,则依次出栈,直到不低于栈顶元素的优先级或者匹配到左括号,此符号进栈。若优先级高于栈顶元素,则直接进栈。最终表达式不包含左右括号

后缀表达式计算结果

从左到右遍历后缀表达式,若遇到数字则进栈,遇到符号,则将栈顶的两个数字出栈进行计算,并将结果进栈,依次计算直到最后,即为结果

示例程序


/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*

  > Author: xiaojunyu/LunaW
  > Mail  : xiaojunyu@lunaw.cn
  > Gmail : lunaw.cn@gmail.com
  > Blog  : http://blog.csdn.net/lunaw
  > Web   : http://lunaw.cn

 *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/

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

#define Number 1
#define Symbol 2
#define True 1
#define False 0

typedef struct Node {
    double number;
    char symbol;
    char type;
    struct Node *next;
} Node, *NodePtr;

typedef struct LinkNode {
    NodePtr head;
} LinkNode;

int CheckExp(char *exp);    // 粗略检查字符串

int IsEmpty(LinkNode * headP);  // 判断栈链是否为空
int Push(LinkNode * headP, Node e); // 入栈
int Pop(LinkNode * headP, NodePtr e);   // 出栈
int TailInsert(LinkNode * headP, Node e);   // 尾插
int PrintList(LinkNode * headP);    // 输出栈
int FreeList(LinkNode * headP); // 释放

int ComparePriority(LinkNode * headP, char symbol); // 比较优先级
int PostfixExpression(LinkNode * headP, char *exp); // 变后缀表达式
double Cal(LinkNode * postfix); // 后缀表达式计算结果
double Math(double A, double B, char C);    // 加减乘除

int main(void)
{
    double result;
    LinkNode postfix;
    char expC[512];

    printf("Please Input (+-*/) : ");
    fgets(expC, sizeof(expC), stdin);

    if (!CheckExp(expC)) {
        printf("Expression error !\n");
        return -1;
    }

    postfix.head = NULL;
    // 变后缀表达式
    PostfixExpression(&postfix, expC);
    // 输出后缀表达式
    printf("Postfix Expression : ");
    PrintList(&postfix);
    // 计算后缀表达式
    result = Cal(&postfix);
    FreeList(&postfix);
    printf("Result : %g\n", result);
    return 0;
}

int CheckExp(char *exp)
{
    int i, status;
    for (i = 0, status = 0; i < (int)strlen(exp); i++) {
        if ((exp[i] >= '0' && exp[i] <= '9') || exp[i] == '+' || exp[i] == '-' || exp[i] == '*' || exp[i] == '/'
            || exp[i] == '(' || exp[i] == ')' || exp[i] == ' ' || exp[i] == '.' || exp[i] == '\n') {
            status++;
        }
    }
    if (status == (int)strlen(exp)) {
        return True;
    } else {
        return False;
    }
}

double Math(double A, double B, char C)
{
    double result;
    switch (C) {
    case '+':
        result = A + B;
        break;
    case '-':
        result = A - B;
        break;
    case '*':
        result = A * B;
        break;
    case '/':
        result = A / B;
        break;
    default:
        result = 0;
    }
    return result;
}

int PostfixExpression(LinkNode * postfix, char *expC)
{
    char number[16];
    double num;
    int i, n;
    Node tmp;
    // 符号栈
    LinkNode symbolexp;
    symbolexp.head = NULL;
    memset(number, '\0', sizeof(number));
    for (i = 0, n = 0; i < (int)strlen(expC); i++) {
        // 遇到空格跳过
        if (expC[i] == ' ') {
            continue;
        }
        // 遇到数字存入临时字符数组中
        if ((expC[i] >= '0' && expC[i] <= '9') || expC[i] == '.') {
            number[n] = expC[i];
            n++;
        } else {
            // 字符数组转换为数字,然后插入到后缀表达式
            if (n) {
                memset(&tmp, 0, sizeof(Node));
                num = strtod(number, NULL);
                tmp.type = Number;
                tmp.number = num;
                tmp.next = NULL;
                TailInsert(postfix, tmp);
                memset(number, '\0', sizeof(number));
                n = 0;
            }
            // 处理符号
            while (True) {
                // 若为表达式最后,全部出栈,插入到后缀表达式
                if (expC[i] == '\n') {
                    while (True) {
                        if (Pop(&symbolexp, &tmp)) {
                            TailInsert(postfix, tmp);
                        } else {
                            break;
                        }
                    }
                    break;
                }
                // 与栈顶符号比较优先级
                if (ComparePriority(&symbolexp, expC[i])) {
                    // 若优先级低于栈顶符号,输出栈顶元素,插入到后缀表达式
                    if (Pop(&symbolexp, &tmp)) {
                        TailInsert(postfix, tmp);
                    }
                } else {
                    // 若优先级高于栈顶符号,进栈
                    // 遇到 ')' 则 '(' 出栈, 且 ')' 不进栈
                    if (expC[i] == ')') {
                        Pop(&symbolexp, &tmp);
                    } else {
                        memset(&tmp, 0, sizeof(Node));
                        tmp.type = Symbol;
                        tmp.symbol = expC[i];
                        tmp.next = NULL;
                        Push(&symbolexp, tmp);
                    }
                    // 显示符号栈的过程
                    // PrintList(&symbolexp);
                    break;
                }
            }
        }
    }
    return 0;
}

double Cal(LinkNode * postfix)
{
    double result = 0;
    double A, B, C;
    NodePtr tmp;
    Node tmpx;
    LinkNode numbexp;
    // 数字栈
    numbexp.head = NULL;
    tmpx.next = NULL;
    for (tmp = postfix->head; tmp != NULL; tmp = tmp->next) {
        if (tmp->type == Number) {
            // 如果遇到数字,进栈
            Push(&numbexp, *tmp);
        } else {
            // 如果遇到符号,栈顶两个数字出栈
            if (Pop(&numbexp, &tmpx)) {
                A = tmpx.number;
            }
            if (Pop(&numbexp, &tmpx)) {
                B = tmpx.number;
            }
            // 计算结果,然后结果进栈
            C = Math(B, A, tmp->symbol);
            memset(&tmpx, 0, sizeof(Node));
            tmpx.type = Number;
            tmpx.number = C;
            tmpx.next = NULL;
            Push(&numbexp, tmpx);
        }
        // 显示符号栈的过程
        // PrintList(&numbexp);
    }
    // 取出栈顶结果
    if (Pop(&numbexp, &tmpx)) {
        result = tmpx.number;
    } else {
        result = 0;
    }
    return result;
}

int PrintList(LinkNode * headP)
{
    NodePtr tmp;
    for (tmp = headP->head; tmp != NULL; tmp = tmp->next) {
        if (tmp->type == Number) {
            printf("%g ", tmp->number);
        } else {
            printf("%c ", tmp->symbol);
        }
    }
    printf("\n");
    return 0;
}

int ComparePriority(LinkNode * headP, char symbol)
{
    if (IsEmpty(headP)) {
        return False;
    }
    char tsym = headP->head->symbol;
    // 这样是相同优先级从右向左计算,根据交换律,不影响结果
    if ((symbol == ')' || (symbol == '+' || symbol == '-')) && tsym != '(') {
        return True;
    } else {
        return False;
    }
}

int FreeList(LinkNode * headP)
{
    NodePtr tmpA, tmpB;
    for (tmpA = headP->head; tmpA != NULL; tmpB = tmpA->next, free(tmpA), tmpA = tmpB) ;
    return 0;
}

int Pop(LinkNode * headP, NodePtr e)
{
    NodePtr tmp;
    if (IsEmpty(headP)) {
        return False;
    }
    memset(e, '\0', sizeof(Node));
    memcpy(e, headP->head, sizeof(Node));
    tmp = headP->head;
    headP->head = headP->head->next;
    free(tmp);
    return True;
}

int TailInsert(LinkNode * headP, Node e)
{
    NodePtr p;
    NodePtr tmp = (NodePtr) calloc(sizeof(Node), 1);
    memcpy(tmp, &e, sizeof(Node));
    if (IsEmpty(headP)) {
        headP->head = tmp;
        headP->head->next = NULL;
    } else {
        for (p = headP->head; p->next != NULL; p = p->next) ;
        p->next = tmp;
        p->next->next = NULL;
    }
    return 0;
}

int Push(LinkNode * headP, Node e)
{
    NodePtr tmp = (NodePtr) calloc(sizeof(Node), 1);
    memcpy(tmp, &e, sizeof(Node));
    tmp->next = headP->head;
    headP->head = tmp;
    return 0;
}

int IsEmpty(LinkNode * headP)
{
    if (headP->head == NULL) {
        return True;
    } else {
        return False;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值