栈的应用->逆波兰关键点

后缀表达式计算方式
规则:从左至右遍历表达式的每一个数字和符号,遇到数字就进栈,遇到符号,就将栈顶俩个数字出栈并进行运算,运算结果进栈,直到获得结果。
举例:后缀表达式 9 3 1 - 3 * + 10 2 / +
1.初始化一个空栈,这个栈用来对要运算的数字进出使用
2.后缀表达式中前三个都是数字,所以9,3,1进栈。
3.接下来是“ -”,所以栈中的1作为减数,3出栈作为被减数,并运算得到二,然后将二进栈。
4.接着是数字3进栈
5.后面是"*",也就意味着将3和2出栈进行运算,得到的结果6进栈
6.接下来是"+",将6和9出栈相加得到的结果15进栈
7.10和2进栈
8.后面是"/",将10和2出栈进行运算得到的结果5进栈
9.后面的是"+",将15和5出栈相加得到最终结果20
10.将最后结果出栈,栈为空。

既然用了后缀表达式后计算器显得没有这么难,但我们还得学会怎么将一行中缀表达式转换为后缀表达式,否则等于没有学

将中缀表达式转换为后缀表达式
规则:
从左边到右边遍历中缀表达式的每一个数字和符号,若是数字就输出,即成为后缀表达式的一部分,若是符号,则判断其与栈顶符号的优先级,是又括号或优先级不高于栈顶符号,则栈顶元素依次出栈并输出,并将当前符号进栈,直到最终输出后缀表达式为止
举例:9+(3-1)3+10/2
1.初始化一空栈,用来对符号进出栈使用
2.第一个数字是9,输出9,后面是 +号,进栈,
3.第三个是(,依然是符号,因为是左括号,还未配对,所以进栈
4.第四个字符是数字3,输出,总表达式为9 3,接着是 -,进栈
5.接下来是数字1,输出,总表达式为9 3 1,后面是符号),此时,我们需要匹配此前的 (,所以栈顶依次出栈,并输出,直到遇到 (,出栈结束,此时左括号上方只有 -,因此输出 -,总的表达式为9 3 1 -
6.紧接着是符号 * ,因为此时栈顶符号为 +,优先级低于
,因此不输出,*进栈,
接着是数字3,输出,表达式为9 3 1 - 3
7.之后的符号是 +,此时当前栈顶元素 *比这个+优先级更高,因此栈中元素出栈并输出(因为没有比+更低的优先级,所以全部出栈)总表达式为9 3 1 - 3 * +,
8.紧接着是数字10,输出,后面是符号 /,所以进栈
9.最后一个数字2,输出
10.因为到了最后,所以将栈中符号全部输出,得到后缀表达式

掌握这俩个后,简单的计算器就没有这么难了

#include<dtdio.h>
#include<stdlib.h>
#include<>memory.h>
#define MAXSIZE 100
typedef struct MStack
{
 char data[MAXSIZE];
 int top;
};
MStack *InitStack()
{
 MStack *ms;
 ms = (MStack*)malloc(sizeof(MStack));
 memset(ms->data, 0, MAXSIZE);
 ms->top = -1;
 return ms;
}
void PushStack(MStack *ms, char e)
{
 if (ms->top == MAXSIZE - 1)
 {
  printf("栈满溢出");
  return;
 }
 ms->data[++ms->top] = e;
}
void PopStack(MStack *ms, char *e)
{
 if (ms->top == -1)
 {
  printf("栈空!");
  return;
 }
 *e = ms->data[ms->top--];
}
int PriCal(char c)
{
 if (c == '-' || c == '+')return 1;
 if (c == '*' || c == '/')return 2;
 if (c == '(' || c == ')')return 3;
 return false;
}
int main()
{
 MStack *ms;
 MStack *msn;
 msn = InitStack();
 ms = InitStack();
 char above = 9;//保存上一次的输入值,检测输入算式是否合法
 char c;
 char num;
 int e;
 c = getchar();
 //以下是将普通中缀表达式改为后缀表达式
 while (1)
 {
  e = 0;
  if (c <= '9' && c >= '0')
  {
   if (ms->top != -1)
   {
    if (above != '+' && above != '-' && above != '*' && above != '/' && above != '(')
    {
     printf("输入算式有错,请检查后重新运行此程序!");
     return -1;
    }
   }
   while (c <= '9' && c >= '0')
   {
    e = e * 10 + c - '0';
    above = c;
    c = getchar();
   }
   PushStack(msn, (char)(e + '0'));
  }
   if (c == '+' || c == '-' || c == '*' || c == '/')
  {
   if (!(above != ')' || (above <= '9' && above >= '0')))
   {
    printf("输入算式有错,请检查后重新运行此程序!");
    return -1;
   }
   if (ms->top == -1)
    PushStack(ms, c);
   else if (PriCal(ms->data[ms->top]) >= PriCal(c))
   {
    while (PriCal(ms->data[ms->top]) >= PriCal(c))
    {
    if (ms->data[ms->top] == '(')break;
    num = c;
     PopStack(ms, &num);
     PushStack(msn, num);
    }
    PushStack(ms, c);
   }
   else PushStack(ms, c);
  }
  if (c == '(' || c == ')')
  {
   if (c == '(')
   {
    if (above != '+' &&above != '-' &&above != '*' &&above != '/'&&ms->top != -1)
    {
     printf("输入算式有错,请检查后重新运行此程序!");
     return -1;
    }
    PushStack(ms, c);
   }
    
   if (c == ')')
   {
    if (above < '0' || above > '9')
    {
     printf("输入算式有错,请检查后重新运行此程序!");
     return -1;
    }
   while (c != '(')
    {
     PopStack(ms, &c);
     if (c != '(')
      PushStack(msn, c);
    }
   }
  }
  above = c;
  if (c == '\n')break;
  else c = getchar();
 }
 while (msn->top != -1)
 {
  PopStack(msn, &c);
  PushStack(ms, c);
 }
 while (ms->top != -1)
 {
  if (ms->data[ms->top] <= '0' + 255 && ms->data[ms->top] >= '0')//原本数据范围是'0'-'9',如果要计算10以外则需要加大为'0'-'0'+255
  {
   PopStack(ms, &c);
   PushStack(msn, c);
  }
  if (ms->data[ms->top] == '+')
  {
   PopStack(ms, &c);
   PopStack(msn, &c);
   PopStack(msn, &num);
   num = (int)(num - '0') + (int)(c - '0') + '0';
   PushStack(msn, num);
  }

  if (ms->data[ms->top] == '-')
  {
   PopStack(ms, &c);
   PopStack(msn, &c);
   PopStack(msn, &num);
   num = (int)(num - '0') - (int)(c - '0') + '0';
   PushStack(msn, num);
  }
  if (ms->data[ms->top] == '/')
  {
   PopStack(ms, &c);
   PopStack(msn, &c);
   PopStack(msn, &num);
   num = (char)(int)(num - '0') / (int)(c - '0') + '0';
   PushStack(msn, num);
  }
  if (ms->data[ms->top] == '*')
  {
   PopStack(ms, &c);
   PopStack(msn, &c);
   PopStack(msn, &num);
   num = (int)(c - '0')*(int)(num - '0') + '0';
   PushStack(msn, num);
  }
 }
 printf("%d", msn->data[msn->top] - '0');
 return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值