C语言数据结构之栈:中缀表达式的计算
*注:本人技术不咋的,就是拿代码出来和大家看看,代码漏洞百出,完全没有优化,主要看气质,是吧
学了数据结构——栈,当然少不了习题。习题中最难的也是最有意思的就是这个中缀表达式的计算了(可以算+-*/和^,当然也可以带小括号)。搞了很久很久啊,终于搞出来的。简单说一下程序原理:
因为中缀表达式基本没法算(就算可以也肯定会超时),所以得把中缀表达式转为后缀表达式。
程序分为两步
第一步:将中缀表达式转为后缀表达式
创建一个字符串,比如叫get,用于存储后缀表达式
先是输入一个字符串,逐一读取单个字符,当是数字则直接存入get,如果是操作符则:
创建栈,比如叫chas
while循环 当栈顶操作符优先级大于或等于当前操作符则弹出并把栈顶元素赋值给get 直到发现优先级小于当前操作符的栈顶的操作符,小于当前操作符的那个栈顶操作符不弹出 然后将当前操作符压入栈内
当当前操作符为'('则直接压入栈内
当当前操作符为')'则while循环 弹出栈顶操作符并赋值给get直到弹出的是'(' ( '('只弹出不赋值 ) 注意,')'不压入栈中
第二部:计算get
创建int型数组栈,比如ints
逐个读入get
当读到数字压入ints
当读到操作符则弹出两个ints的栈顶元素,并进行相应计算,将计算得到的值压入栈ints中
最后读完get时,ints数组只剩下一个元素了,输出。
自个儿写的稀巴烂源码(c):
- #include <stdio.h>
- #include <string.h>
- #include <math.h>
- int ints[];
- int intt;//ints的top
- char chas[];
- int chat;//chas的top
- int i=, ii=;
- char c;
- char get[];//输入的中缀表达式
- char get2[];//计算得出的后缀表达式
- void intpush(x)//整型栈压栈
- {
- intt++; ints[intt]=x;
- }
- void chapush(x)//字符型栈压栈
- {
- chat++; chas[chat]=x;
- }
- int intpop()//整型栈弹出
- {
- intt--; return ints[intt+];
- }
- char chapop()//字符型栈弹出
- {
- chat--; return chas[chat+];
- }
- void intadd(int x)//整型栈栈顶元素加入新的个位数字
- {
- ints[intt]*=; ints[intt]+=x;
- }
- int find()//get2加入操作符
- {
- c=chapop();
- get2[ii]=' ';
- get2[ii+]=c;
- ii+=;
- if(chat==) return ;
- return ;
- }
- int main()
- {
- intt=; chat=;
- gets(get);
- int lengets=strlen(get);
- for(i=;i<=lengets-;i++)//逐个读取输入的中缀表达式
- {
- if (isdigit(get[i]))//当get[i]为数字时
- {
- get2[ii]=get[i];
- ii++;
- }
- else
- {
- if(get[i]=='(')chapush('(');
- if(get[i]=='^')chapush('^');
- if(get[i]==')')
- {
- c=chapop();
- while(c!='(')
- {
- get2[ii]=' ';
- get2[ii+]=c;
- ii+=;
- c=chapop();
- }
- }
- if(get[i]=='+')
- {
- while(chas[chat]=='+'||chas[chat]=='-'||chas[chat]=='*'||chas[chat]=='/'||chas[chat]=='^')
- {
- if(find()==)break;
- }
- chapush('+');
- }
- if(get[i]=='-')
- {
- while(chas[chat]=='+'||chas[chat]=='-'||chas[chat]=='*'||chas[chat]=='/'||chas[chat]=='^')
- {
- if(find()==)break;
- }
- chapush('-');
- }
- if(get[i]=='*')
- {
- while(chas[chat]=='*'||chas[chat]=='/'||chas[chat]=='^')
- {
- if(find()==)break;
- }
- chapush('*');
- }
- if(get[i]=='/')
- {
- while(chas[chat]=='*'||chas[chat]=='/'||chas[chat]=='^')
- {
- if(find()==)break;
- }
- chapush('/');
- }
- get2[ii]=' ';
- ii++;
- }
- }
- while(chat>)//输出栈内剩余的操作符
- {
- int c=chapop();
- get2[ii]=' ';
- get2[ii+]=c;
- ii+=;
- }
- get2[ii]='@';//加入结束符
- i=;
- while(get2[i]!='@')//当看到结束符停止计算
- {
- if(get2[i]=='+'||get2[i]=='-'||get2[i]=='*'||get2[i]=='/'||get2[i]=='^')
- {
- int a=intpop();int b=intpop();int c;
- if(get2[i]=='+') c=a+b;
- if(get2[i]=='-') c=b-a;
- if(get2[i]=='*') c=a*b;
- if(get2[i]=='/') c=b/a;
- if(get2[i]=='^') c=pow(b,a);
- intpush(c);
- }
- else
- {
- if(get2[i]!=' ')
- {
- intpush(get2[i]-);
- ii=;
- while(get2[i+ii]!=' ')
- {
- intadd(get2[i+ii]-);
- ii++;
- }
- i+=ii-;
- }
- }
- i++;
- }
- printf("%d",ints[]);
- return ;
- }
样例输入:
1+(3+2)*(7^2+6*9)/(2)
样例输出:
258
好了,就写到这了。(原题:信息学奥赛一本通C++版 数据结构 栈 上机练习4 calc)//别问我为什么C++的书的练习我写的是C,我不会告诉你是因为那样文件名可以少打两个p
对了,再说一下,其实这玩意完全没必要写这么长,最NB办法:
右键桌面:新建文本文件
双击打开新建文本文件.txt,输入如下脚本:
- @echo off
- set /p get=
- set /a ans=%get%
- echo %ans%
- pause
- exit::可以不要这句exit
右键新建文本文件,重命名为:calc.bat
双击打开
样例输入:
1+(3+2)*(7*7+6*9)/(2)
样例输出:
258
除了乘方没法算,别的都一样
呵呵,我不想多什么了……
最新更新(2016/7/4):新代码,同样的功能,更快的速度,更短的代码
- #include <stdio.h>
- #include <string.h>
- #include <math.h>
- char ops[101];
- int opsi=0;
- int ovs[101];
- int ovsi=0;
- void opsin(char c)
- {
- opsi++;
- ops[opsi]=c;
- }
- void ovsin(int num)
- {
- ovsi++;
- ovs[ovsi]=num;
- }
- char opsout()
- {
- opsi--;
- return ops[opsi+1];
- }
- int ovsout()
- {
- ovsi--;
- return ovs[ovsi+1];
- }
- void count2(char c)
- {
- int b=ovsout();
- int a=ovsout();
- switch(c)
- {
- case '+':ovsin(a+b);break;
- case '-':ovsin(a-b);break;
- case '*':ovsin(a*b);break;
- case '/':ovsin(a/b);break;
- case '^':ovsin(pow(a,b));break;
- }
- }
- int count(const char *str)
- {
- ops[0]=0;
- int stri=0,lenstr=strlen(str);
- while(stri<=lenstr-1)
- {
- if(str[stri]=='(')opsin('(');
- else
- if(str[stri]=='^')opsin('^');
- else
- if(str[stri]==')')
- {
- char c=opsout();
- while(c!='(')
- {
- count2(c);
- c=opsout();
- }
- }
- else
- if(str[stri]=='+')
- {
- while(ops[opsi]=='+'||ops[opsi]=='-'||ops[opsi]=='*'||ops[opsi]=='/'||ops[opsi]=='^')count2(opsout());
- opsin('+');
- }
- else
- if(str[stri]=='-')
- {
- while(ops[opsi]=='+'||ops[opsi]=='-'||ops[opsi]=='*'||ops[opsi]=='/'||ops[opsi]=='^')count2(opsout());
- opsin('-');
- }
- else
- if(str[stri]=='*')
- {
- while(ops[opsi]=='*'||ops[opsi]=='/'||ops[opsi]=='^')count2(opsout());
- opsin('*');
- }
- else
- if(str[stri]=='/')
- {
- while(ops[opsi]=='*'||ops[opsi]=='/'||ops[opsi]=='^')count2(opsout());
- opsin('/');
- }
- else//num
- {
- if(stri>0)
- {
- if(str[stri-1]-48>=0&&str[stri-1]-48<=9)
- ovsin(ovsout()*10+str[stri]-48);
- else
- ovsin(str[stri]-48);
- }
- else
- ovsin(str[stri]-48);
- }
- stri++;
- }
- while(ovsi>1)count2(opsout());
- return ovs[1];
- }
- int main()
- {
- char s[101];
- gets(s);
- printf("%d",count(s));
- return 0;
- }
C语言数据结构之栈:中缀表达式的计算的更多相关文章
- 适用于实数范围的中缀表达式的 + - * / ( ) 计算(C++实现)
核心算法: mid=FormatMid(mid); //格式化中缀表达式 JudgeLegalMid(mid); //判断中缀表达式的合法性 MidToPost mtp(mid); mtp.ToPos ...
- C++实现顺序栈类求解中缀表达式的计算
控制台第一行打印的数值为使用形如以下方式得到的结果: cout << +*(+)*/- << endl; 即第一个待求解表达式由C++表达式计算所得结果,以用于与实现得出的结果 ...
- C语言数据结构之栈:括号匹配
括号匹配这是个很简单的题目,如果只有小括号,就模拟进栈和出栈的过程就行了: 注:输入时'@'作为结束标志 #include <stdio.h> int main() { freopen(& ...
- C语言数据结构链栈(创建、入栈、出栈、取栈顶元素、遍历链栈中的元素)
/**创建链栈*创建一个top指针代表head指针*采用链式存储结构*采用头插法创建链表*操作 创建 出栈 入栈 取栈顶元素*创建数据域的结构体*创建数据域的名称指针*使用随机函数对数据域的编号进行赋 ...
- Infix expressions 中缀表达式
中缀表达式的计算 利用两个栈来实现,操作数栈,操作符栈 只支持个位数运算 最后必须输入一个'#' #include<iostream> using namespace std; templ ...
- Java堆栈的应用2----------中缀表达式转为后缀表达式的计算Java实现
1.堆栈-Stack 堆栈(也简称作栈)是一种特殊的线性表,堆栈的数据元素以及数据元素间的逻辑关系和线性表完全相同,其差别是线性表允许在任意位置进行插入和删除操作,而堆栈只允许在固定一端进行插入和删除 ...
- C语言- 基础数据结构和算法 - 09 栈的应用_中缀表达式转后缀表达式20220611
09 栈的应用_中缀表达式转后缀表达式20220611 听黑马程序员教程<基础数据结构和算法 (C版本)>, 照着老师所讲抄的, 视频地址https://www.bilibili.com/ ...
- 栈的简单应用之中缀表达式转后缀表达式(C语言实现逆波兰式)
一.前言 普通人在书写计算式时会选择中缀表达式,这样符合人脑的认知习惯.可计算机处理时后缀表达式才能使处理速度更快,其原因是利用堆栈结构减少计算机内存访问.同时它也是一个很好锻炼栈这个数据结构的应 ...
- Python与数据结构[1] -> 栈/Stack[1] -> 中缀表达式与后缀表达式的转换和计算
中缀表达式与后缀表达式的转换和计算 目录 中缀表达式转换为后缀表达式 后缀表达式的计算 1 中缀表达式转换为后缀表达式 中缀表达式转换为后缀表达式的实现方式为: 依次获取中缀表达式的元素, 若元素为操 ...
随机推荐
- Android(java)学习笔记106-2:反射机制
1.反射机制: JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为 ...
- this的分析
this是js中的一个关键字,当函数运行时,会自动生成的一个对象,只能在函数内部使用.随着函使用场合不同,this值会变化,但是始终指向调用函数的那个对象. 1.纯粹的函数调用 function bo ...
- android 编写动画
1.在编写动画的时候需要新建一个xml 新建的步骤是选中res单击右键选择Android resource file 然后弹出一个框 ,然后再Resource Type 里面选择Animation 然 ...
- android开发之路11(用SharedPreferences存储数据)
Android平台给我们提供了一个SharedPreferences类,实际上SharedPreferences处理的就是一个key-value(键值对),它是 一个轻量级的存储类,特别适合用于保存软 ...
- linux 基本命令 [转]
linux 基本命令 1.ls (list 显示当前目录下文件和目录 ls -l 详细显示 =ll ) [root@linux ~]# ls [-aAdfFhilRS] 目录名称 [root@lin ...
- Java汉字转成汉语拼音工具类
Java汉字转成汉语拼音工具类,需要用到pinyin4j.jar包. import net.sourceforge.pinyin4j.PinyinHelper; import net.sourcefo ...
- Eclipse 中引用其他项目及项目打包
1.建立工程project1; 2.建立class文件ClassA: package com.test; public class ClassA{ public static String getCl ...
- Windwos下Apache的缓存设置
1.打开httpd.conf,找到以下几个Module并将其启用(如果没有,可以自行添加) mod_proxy.so(module_proxy) m ...
- 让footer固定在页面(视口)底部(CSS-Sticky-Footer)
让footer固定在页面(视口)底部(CSS-Sticky-Footer) 这是一个让网站footer固定在浏览器(页面内容小于浏览器高度时)/页面底部的技巧.由HTML和CSS实现,没有令人讨厌的h ...
- Six important .NET concepts 【Turn】
Introduction This article will explain six important concepts: stack, heap, value types, reference t ...