真真真的觉得数据结构好难,但是秉着“为之则易,不为则难”的校训,我终于迈出了这一步,我要解决掉这个问题!
实现一个简单的计算器,输入一个包含圆括号、加、减、乘、除、求余等符号组成的算术表达式字符串,输出该算术表达式的值。
Last in first out
两种实现方式(都为顺序存储结构):
数组存储
链式存储
分析完了以后,就让我们开始吧!
首先应该是栈的实现,现在我要开始我的创作了。
#include
#include
#define MaxSize 100
#define ElementType char
typedef struct SNode* Stack;
int isEmpty(Stack s);
void push(Stack s,ElementType item);
ElementType pop(Stack s);
struct SNode
{
ElementType Data[MaxSize]; //ElementType 可以是任意数据类型,使用的时候用宏定义即可
int top; //定义一个头指针,实际上记录的是数组的下标 -1:空栈
};
//入栈操作
void push(Stack s,ElementType item)
{
if(isEmpty(s)){
printf("栈是空的");
return;
}
else{
s->Data[++(s->top)]=item;
}
}
// 出栈操作
ElementType pop(Stack s)
{
if(isEmpty(s)){
return 'e';
}
else{
return s->Data[s->top--];//先返回再将数组下标减一
}
}
//判断栈是否为空
int isEmpty(Stack s)
{
if(s->top==0)
return 1;
else
return 0;
}
//初始化
Stack creatStack()
{
Stack s=(struct SNode*)malloc(sizeof(struct SNode*));
s->top=-1;//空栈
return s;
}
到这里就完成了第一步:栈的创建
然后进行第二部,将中缀表达式转化成后缀表达式
我这里做一个抽象处理:假设算式中的数字使用一个字符表示的,来简化问题。
运算符的优先级:符号的集合为:+ - * / ( )
‘(’ 优先级别不在栈内是最高,在栈内时优先级别低【】
')'优先级别最低
然后是* / + -
生成一个方法获取运算符的优先级:
int getPri(char c)
{
switch(c){
case '*':;
case '/':return 3;
case '+':;
case '-':return 2;
case '#':return 0;
}
}
将中缀转化成后缀表达式
char* ReversePolishNotation(char* Notation,Stack s)
{ char newNotation[20];
int len=strlen(Notation);
int j=0;//记录newNotation当前的位置
for(int i=0;i<len;i++){
//是数字直接输出
if(Notation[i]>='0'&&Notation[i]<='9'){
newNotation[j++]=Notation[i];
}
//左括号
else if(Notation[i]=='('){
push(s,Notation[i]);
}
//右括号
else if(Notation[i]==')'){
char c=pop(s);
newNotation[j++]=c;
while(c!='('){
c=pop(s);
newNotation[j++]=c;
}
c=pop(s);
if(c!='('){
printf("括号不匹配");
}
}
/*
*运算符
*/
else{
char cc=pop(s);
push(s,cc);
//如果当前符号的优先级大于栈顶运算符的优先级,则入栈
if(getPri(cc)<getPri(Notation[i])){
push(s,Notation[i]);
}
else {
cc=pop(s);
newNotation[j++]=cc;
cc=pop(s);
push(s,cc);
while(getPri(cc)>=getPri(Notation[i])){
cc=pop(s);
newNotation[j++]=cc;
cc=pop(s);
push(s,cc);
}
}
}
}
return newNotation;
}
测试::
int main()
{
Stack s=creatStack();
char* notation="2+9/3-5";
char* n=ReversePolishNotation(notation,s);
printf("%s",n);
}
结果截图:
出错了,开始找错误。
不知道屏幕前的你是否找到了错误呢?
终于找到错误了,错误地方有些琐碎,直接总结。
正确代码附上:
#include
#include
#include
#define MaxSize 20
#define ElementType char
typedef struct SNode* Stack;
int isEmpty(Stack s);
void push(Stack s,ElementType item);
ElementType pop(Stack s);
int getPri(char c);
ElementType getEle(Stack s);
struct SNode
{
ElementType Data[MaxSize]; //ElementType 可以是任意数据类型,使用的时候用宏定义即可
int top; //定义一个头指针,实际上记录的是数组的下标 -1:空栈
};
//入栈操作
void push(Stack s,ElementType item)
{
if(s->top<MaxSize-1){
s->Data[++(s->top)]=item;
}
else{
printf("栈满");
}
}
// 出栈操作
ElementType pop(Stack s)
{
if(isEmpty(s)){
printf("s空");
return s->Data[0];
}
else{
return s->Data[(s->top)--];//先返回再将数组下标减一
}
}
//判断栈是否为空
int isEmpty(Stack s)
{
if(s->top==0)
return 1;
else if(s->top>0)
return 0;
}
//初始化
Stack creatStack()
{
Stack s=(struct SNode*)malloc(sizeof(struct SNode));
s->top=0;//空栈
s->Data[0]='#';
return s;
}
void ReversePolishNotation(char* Notation,Stack s)
{ char newNotation[20];
int len=strlen(Notation);
int j=0;//记录newNotation当前的位置
for(int i=0;i<len;i++){
//是数字直接输出
if(Notation[i]>='0'&&Notation[i]<='9'){
newNotation[j++]=Notation[i];
}
//左括号压入堆栈
else if(Notation[i]=='('){
push(s,Notation[i]);
}
//遇到右括号,将栈顶的符号弹出并输出,直至遇到左括号
else if(Notation[i]==')'){
char c=getEle(s);
while(c!='('){
c=pop(s);
newNotation[j++]=c;
c=getEle(s);
}
pop(s);
}
/*
*运算符
*/
else{
char cc=getEle(s);//cc当前栈顶运算符
//算式当前项的运算符优先级>s栈顶运算符的优先级,将它压栈
if(getPri(Notation[i])>getPri(cc)){
push(s,Notation[i]);
}
//否则就将s栈顶的运算符弹出并输出,在比较新的栈顶运算符,直到当前运算符优先级>栈顶运算符
else {
cc=pop(s);
newNotation[j++]=cc;
cc=getEle(s);
while(getPri(Notation[i])<=getPri(cc)){
cc=pop(s);
newNotation[j++]=cc;
cc=getEle(s);
}
push(s,Notation[i]);
}
}
}
// //最后将栈中的运算符都输出
char c=getEle(s);
while(s->top>0&&c!='#'){
newNotation[j++]=c;
pop(s);
c=getEle(s);
}
printf("%s",newNotation);
}
int getPri(char c)
{
switch(c){
case '*':;
case '/':return 3;
case '+':;
case '-':return 2;
case '(':return 1;
case '#':return 0;
}
}
//获取栈顶元素
ElementType getEle(Stack s)
{
char c=pop(s);
if(c!='#')
push(s,c);
return c;
}
int main()
{
Stack s=creatStack();
char notation[20]="(2*(9+6/3-5)+4)";
ReversePolishNotation(notation,s);
}