文章目录
⭐️写在前面的话⭐️
📒博客主页: 程序员好冰
🎉欢迎 【点赞👍 关注🔎 收藏⭐️ 留言📝】
📌本文由 程序员好冰 原创,CSDN 首发!
📆入站时间: 🌴2022 年 07 月 13 日🌴
✉️ 是非不入松风耳,花落花开只读书。
💭推荐书籍:📚《Java编程思想》,📚《Java 核心技术卷》
💬参考在线编程网站:🌐牛客网🌐力扣
🍭 作者水平很有限,如果发现错误,一定要及时告知作者哦!感谢感谢!🍭
逆波兰表达式
代码只实现了小括号的匹配,大括号和中括号的匹配没有实现;
只能够实现整数类型的表达式运算;
只限处理两位数的表达式,两位数以上的没有实现。
0、构建基本的栈结构
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
#define OK 1
#define ERROR 0
#define MAX_SIZE 100
typedef char ElemType;
typedef int Status;
typedef struct LNode
{
ElemType data;
struct LNode *next;
}LNode;
typedef struct LinkStack
{
int count;
struct LNode *top;
}LinkStack;
Status InitStack(LinkStack* L)
{
L->top=(LNode*)malloc(sizeof(LNode));
if(!L->top){
return ERROR;
}
L->top=NULL;
L->count=0;
return OK;
}
Status StackIsEmpty(LinkStack L)
{
if(L.count==0){
return OK;
}
if(L.count!=0){
return ERROR;
}
return OK;
}
ElemType GetTop(LinkStack L)
{
if(StackIsEmpty(L)){
return ERROR;
}
return L.top->data;
}
Status Push(LinkStack *L,ElemType e)
{
LNode *s=(LNode*)malloc(sizeof(LNode));
s->data=e;
s->next=L->top;
L->top=s;
L->count++;
return OK;
}
LNode* Pop(LinkStack *L)
{
if(StackIsEmpty(*L)){
return ERROR;
}
LNode *temp;
temp=L->top;
L->top=L->top->next;
L->count--;
return temp;
}
Status PrintStack(LinkStack L)
{
if(L.top==NULL){
return ERROR;
}
while(L.top){
printf("%c",L.top->data);
L.top=L.top->next;
}
printf("\n");
return OK;
}
1、中缀表达式转为后缀表达式
准备一个存放运算结果的数组和一个判断操作符的栈
从左往右扫描表达式
遇到数字,直接存入数组中;
遇到运算符,
首先解决分母为0的问题,
再判断栈如果为空,直接入栈,
栈不为空,比较该运算符和此时栈顶元素的优先级
高于,直接入栈;低于,依次出栈,直到高于栈顶元素的优先级;
遇到左括号,直接入栈;
遇到右括号,依次将栈顶元素存入数组,遇到左括号结束,再将左括号弹出;
最后表达式遍历完毕,依次将栈中的元素弹出存入数组中。
1.1封装需要的方法
//判断输入的字符是否为数值
int is_Number(char c)
{
if(c>='0'&&c<='9'){
return 1;
}
return 0;
}
//判断输入的字符是否为运算符
int is_Operator(char c)
{
if(c=='+'||c=='-'||c=='*'||c=='/'){
return 1;
}
return 0;
}
//比较加减乘除的优先级
/*加减的优先级为1;乘除的优先级为2*/
int comp_Priority(char c)
{
int level=0;
switch(c)
{
case '+':
case '-':
level=1;
break;
case '*':
case '/':
level=2;
break;
}
return level;
}
//判断是否为左括号
int is_Left(char c)
{
if(c=='('){
return 1;
}
return 0;
}
//判断是否为右括号
int is_Right(char c)
{
if(c==')'){
return 1;
}
return 0;
}
//初始化数组,每一位都放‘/0’
char result[MAX_SIZE]={0};
//存放后缀表达式的数组
void input(char c)
{
static int index=0;
result[index++]=c;
}
1.2 主方法
//将中缀表达式转换为后缀表达式
Status Trans_Postfix_Notation(char *str)
{
int i;
//初始化一个符号工作栈
LinkStack L;
InitStack(&L);
i=0;
while(str[i]!='\0'){
//情况1:是数字
if(is_Number(str[i])){
if(is_Number(str[i+1])){
input(str[i]);
}
//后一个可能是运算符或者括号
if(!is_Number(str[i+1])){
input(str[i]);
input(' ');
}
}
//情况2:是运算符
/*如果栈为空,运算符直接压栈*/
/*如果栈为不为空,要进栈的运算符与栈顶运算符比较优先级*/
/*优先级高,继续压栈*/
/*优先级低,出栈*/
if(is_Operator(str[i])){
if(str[i]=='/'&&str[i+1]=='0'){
printf("表达式中分母不能为0.\n");
return ERROR;
}
if(!StackIsEmpty(L)){
//比较优先级
/*1、要压入的,比栈顶的高,直接压入*/
/*2、要压入的,比栈顶的低*/
if(comp_Priority(str[i])<=comp_Priority(GetTop(L))){
while(!StackIsEmpty(L)&&comp_Priority(str[i])<=comp_Priority(GetTop(L))){
input(Pop(&L)->data);
input(' ');
}
}
Push(&L,str[i]);//两种情况公有的部分
}
if(StackIsEmpty(L)){
Push(&L,str[i]);
}
}
//情况3:是左括号
if(is_Left(str[i])){
Push(&L,str[i]);
}
//情况4:是右括号
if(is_Right(str[i])){
while(!is_Left(GetTop(L))){
input(Pop(&L)->data);
input(' ');
if(StackIsEmpty(L)){
printf("表达式的括号不匹配.\n");
return ERROR;
}
}
Pop(&L);//弹出匹配的左括号
}
//情况5:非法字符
if(!is_Number(str[i])&&!is_Operator(str[i])&&!is_Left(str[i])&&!is_Right(str[i])){
printf("存在非法字符.\n");
return ERROR;
}
i++;
}
//情况6:字符串循环完毕
while(!StackIsEmpty(L)){
input(Pop(&L)->data);
input(' ');
}
printf("%s",result);
return OK;
}
2、计算后缀表达式的值
从左往右扫描表达式,
遇到数字就将其压入栈,注意如果是两位数,需要多取一次
遇到运算符说明可以计算,这时取出依次取出栈顶的两个元素进行运算符运算,
运算完毕,将计算结果再压入栈
直到栈中只留下最后一个元素
这个元素就是表达式的计算结果。
2.1 封装需要的方法
//将字符串转为整型
int string_to_int(char *temp)
{
return atoi(temp);
}
//将字符类型转为整型
int char_to_int(char temp)
{
return temp-'0';
}
//将整型转为字符类型
char int_to_char(int temp)
{
return temp+'0';
}
int Calculator(int a,int b,char temp)
{
int result2=0;
switch(temp)
{
case '+':
result2=a+b;
break;
case '-':
result2=a-b;
break;
case '*':
result2=a*b;
break;
case '/':
result2=a/b;
break;
}
return result2;
}
2.2 主方法
int comp_Rev_Polish_Notation()
{
LinkStack S;//存放
InitStack(&S);
int i=0;
int sum=0;//记录最终的结果
int a,b;//需要进行运算的两个操作数
int c;//保留两数的计算结果
while(result[i]!='\0'){
if(result[i]!=' '){
if(is_Number(result[i])){
if(!is_Number(result[i+1])){
Push(&S,result[i]);
}
if(is_Number(result[i+1])){//解决两位数的问题
a=char_to_int(result[i]);
b=char_to_int(result[i+1]);
c=a*10+b;
Push(&S,int_to_char(c));
i+=2;
continue;
}
}
if(is_Operator(result[i])){
a=char_to_int(Pop(&S)->data);
b=char_to_int(Pop(&S)->data);
c=Calculator(b,a,result[i]);
Push(&S,int_to_char(c));
}
}
i++;
}
if(S.count==1){
sum=char_to_int(Pop(&S)->data);
}
return sum;
}
3、主函数
int main()
{
char str[MAX_SIZE]={0};//存放手动输入的中缀表达式
char ch;
int i=0;
int sum=0;//记录表达式的最终结果
printf("链栈创建成功,请继续操作.\n");
printf("\n==========================\n");
printf("通过逆波兰表示法计算表达式的值.\n");
printf("请输入一个中缀表达式:");
while((ch=getchar())!='\n'){
str[i]=ch;
i++;
}
str[i]='\0';
printf("\n");
printf("对应的后缀表达式(逆波兰表达式)为:");
Trans_Postfix_Notation(str);
printf("\n");
printf("\n");
sum=comp_Rev_Polish_Notation();
printf("表达式的值为:%d.\n",sum);
printf("\n");
printf("==========================\n");
return 0;
}
程序源码
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
#define OK 1
#define ERROR 0
#define MAX_SIZE 100
typedef char ElemType;
typedef int Status;
typedef struct LNode
{
ElemType data;
struct LNode *next;
}LNode;
typedef struct LinkStack
{
int count;
struct LNode *top;
}LinkStack;
Status InitStack(LinkStack* L)
{
L->top=(LNode*)malloc(sizeof(LNode));
if(!L->top){
return ERROR;
}
L->top=NULL;
L->count=0;
return OK;
}
Status StackIsEmpty(LinkStack L)
{
if(L.count==0){
return OK;
}
if(L.count!=0){
return ERROR;
}
return OK;
}
ElemType GetTop(LinkStack L)
{
if(StackIsEmpty(L)){
return ERROR;
}
return L.top->data;
}
Status Push(LinkStack *L,ElemType e)
{
LNode *s=(LNode*)malloc(sizeof(LNode));
s->data=e;
s->next=L->top;
L->top=s;
L->count++;
return OK;
}
LNode* Pop(LinkStack *L)
{
if(StackIsEmpty(*L)){
return ERROR;
}
LNode *temp;
temp=L->top;
L->top=L->top->next;
L->count--;
return temp;
}
Status PrintStack(LinkStack L)
{
if(L.top==NULL){
return ERROR;
}
while(L.top){
printf("%c",L.top->data);
L.top=L.top->next;
}
printf("\n");
return OK;
}
/*--------------------------------*/
//判断输入的字符是否为数值
int is_Number(char c)
{
if(c>='0'&&c<='9'){
return 1;
}
return 0;
}
//判断输入的字符是否为运算符
int is_Operator(char c)
{
if(c=='+'||c=='-'||c=='*'||c=='/'){
return 1;
}
return 0;
}
//比较加减乘除的优先级
/*加减的优先级为1;乘除的优先级为2*/
int comp_Priority(char c)
{
int level=0;
switch(c)
{
case '+':
case '-':
level=1;
break;
case '*':
case '/':
level=2;
break;
}
return level;
}
//判断是否为左括号
int is_Left(char c)
{
if(c=='('){
return 1;
}
return 0;
}
//判断是否为右括号
int is_Right(char c)
{
if(c==')'){
return 1;
}
return 0;
}
//初始化数组,每一位都放‘/0’
char result[MAX_SIZE]={0};
//存放后缀表达式的数组
void input(char c)
{
static int index=0;
result[index++]=c;
}
//将中缀表达式转换为后缀表达式
Status Trans_Postfix_Notation(char *str)
{
int i;
//初始化一个符号工作栈
LinkStack L;
InitStack(&L);
i=0;
while(str[i]!='\0'){
//情况1:是数字
if(is_Number(str[i])){
if(is_Number(str[i+1])){
input(str[i]);
}
//后一个可能是运算符或者括号
if(!is_Number(str[i+1])){
input(str[i]);
input(' ');
}
}
//情况2:是运算符
/*如果栈为空,运算符直接压栈*/
/*如果栈为不为空,要进栈的运算符与栈顶运算符比较优先级*/
/*优先级高,继续压栈*/
/*优先级低,出栈*/
if(is_Operator(str[i])){
if(str[i]=='/'&&str[i+1]=='0'){
printf("表达式中分母不能为0.\n");
return ERROR;
}
if(!StackIsEmpty(L)){
//比较优先级
/*1、要压入的,比栈顶的高,直接压入*/
/*2、要压入的,比栈顶的低*/
if(comp_Priority(str[i])<=comp_Priority(GetTop(L))){
while(!StackIsEmpty(L)&&comp_Priority(str[i])<=comp_Priority(GetTop(L))){
input(Pop(&L)->data);
input(' ');
}
}
Push(&L,str[i]);//两种情况公有的部分
}
if(StackIsEmpty(L)){
Push(&L,str[i]);
}
}
//情况3:是左括号
if(is_Left(str[i])){
Push(&L,str[i]);
}
//情况4:是右括号
if(is_Right(str[i])){
while(!is_Left(GetTop(L))){
input(Pop(&L)->data);
input(' ');
if(StackIsEmpty(L)){
printf("表达式的括号不匹配.\n");
return ERROR;
}
}
Pop(&L);//弹出匹配的左括号
}
//情况5:非法字符
if(!is_Number(str[i])&&!is_Operator(str[i])&&!is_Left(str[i])&&!is_Right(str[i])){
printf("存在非法字符.\n");
return ERROR;
}
i++;
}
//情况6:字符串循环完毕
while(!StackIsEmpty(L)){
input(Pop(&L)->data);
input(' ');
}
printf("%s",result);
return OK;
}
//封装的函数
//将字符串转为整型
int string_to_int(char *temp)
{
return atoi(temp);
}
//将字符类型转为整型
int char_to_int(char temp)
{
return temp-'0';
}
//将整型转为字符类型
char int_to_char(int temp)
{
return temp+'0';
}
int Calculator(int a,int b,char temp)
{
int result2=0;
switch(temp)
{
case '+':
result2=a+b;
break;
case '-':
result2=a-b;
break;
case '*':
result2=a*b;
break;
case '/':
result2=a/b;
break;
}
return result2;
}
int comp_Rev_Polish_Notation()
{
LinkStack S;//存放
InitStack(&S);
int i=0;
int sum=0;//记录最终的结果
int a,b;//需要进行运算的两个操作数
int c;//保留两数的计算结果
while(result[i]!='\0'){
if(result[i]!=' '){
if(is_Number(result[i])){
if(!is_Number(result[i+1])){
Push(&S,result[i]);
}
if(is_Number(result[i+1])){//解决两位数的问题
a=char_to_int(result[i]);
b=char_to_int(result[i+1]);
c=a*10+b;
Push(&S,int_to_char(c));
i+=2;
continue;
}
}
if(is_Operator(result[i])){
a=char_to_int(Pop(&S)->data);
b=char_to_int(Pop(&S)->data);
c=Calculator(b,a,result[i]);
Push(&S,int_to_char(c));
}
}
i++;
}
if(S.count==1){
sum=char_to_int(Pop(&S)->data);
}
return sum;
}
int main()
{
char str[MAX_SIZE]={0};//存放手动输入的中缀表达式
char ch;
int i=0;
int sum=0;//记录表达式的最终结果
printf("链栈创建成功,请继续操作.\n");
printf("\n==========================\n");
printf("通过逆波兰表示法计算表达式的值.\n");
printf("请输入一个中缀表达式:");
while((ch=getchar())!='\n'){
str[i]=ch;
i++;
}
str[i]='\0';
printf("\n");
printf("对应的后缀表达式(逆波兰表达式)为:");
Trans_Postfix_Notation(str);
printf("\n");
printf("\n");
sum=comp_Rev_Polish_Notation();
printf("表达式的值为:%d.\n",sum);
printf("\n");
printf("==========================\n");
return 0;
}
运行截图
🚀先看后赞,养成习惯!🚀
🚀 先看后赞,养成习惯!🚀
🎈觉得文章写得不错的老铁们,点赞评论关注走一波!谢谢啦!🎈