您的位置:首页 > 理论基础 > 数据结构算法

数据结构之利用栈将中缀表达式求解后缀表达式

2014-04-03 11:10 295 查看
开头老是不知道怎么表达,表达能力也实在有限。在学数据结构,栈,顺序栈和链栈的blog已经写了,想想有几天没把windows编程里面的消息处理的blog给写了,明天图书  馆开门再去那里用电脑写,那些是自学过了的,写起来没那么麻烦,数据结构这个在学,没写一次blog之前都自己动手实现一大堆代码敢往上贴。算法导论这本书已经练得炉火出清的大神见笑了。

利用栈来实现进制转换,求后缀表达式的值和将中缀表达式转换成后缀表达式是这篇blog的目的。

进制转换。代码实现了将二进制转换成十进制,将二进制转换成八进制。转换成十六进制的和转换成八进制的,我确实看不出有多少不同,所以就没写将二进制转换成十六进制了。

简单讲下栈实现进制转换原理:

把存放二进制的字符串放进栈中。我们输入时这样子的,高位放在字符串的前面。这和我们内存中小端存储不一样,小端存储是将高位存放高字节,低位存放在低字节,用十六进制查看器查看pe文件中的RVA就有点DT,从后面读起。扯远了。高位先进栈,把所有位进栈后,在弹栈乘上对应的二的次方就行了。再迭代求和,如下所示:

1011B = (1*2^0 + 1*2^1 + 0*2^2 +1*2^3)D 

将二进制转换成八进制也很简单,用三位二进制来表示个八进制,

至于后缀表示式的求解原理,个人写的时候也百度,也Google,也找书看。大概如下:

①从头到尾扫描表达式

②如果是数字,进栈,如果是运算符,从栈中弹出两个数进行这个运算符的运算,然后将结果push进栈。

③依次循环,知道表达式扫描完

最后在栈中的结果就是最终后缀表达式的结果

上面这个有缺陷,所有的运算符都是二元运算符,因为要弹两个数进行运算。

具体看代码,原理说起来都很容易理解,写起来才发现有问题的。我有个同学,很好的同学,每次上程序课他都好像很牛逼的样子,什么都理解的样子,但是回到宿舍我从来没见他写过代码,就算我刚刚跟他讨论完ACM的题目,他还是没有去写代码,这样我确实很失望。后来就再也不跟他讨论技术了。说起来本人也是个性格非常怪有点孤僻的人。

将中缀表达式转换成后缀表达式

这个比较重要,我网上查的没发现有人贴c语言实现的代码。都是Java实现的。说起Java也有点小郁闷,本人Java不是很好,学的时候就写了个模拟ATM取款机的小软件,后来才发现自己傻,所有界面设计都自己去动手写,明明就有插件。(到现在还是没用插件),而且Java好像在桌面开发上不好吧。因为将软件打包成jar包的话,客户不装jdk就无法跑起来,要是再用软件打包成exe格式的文件的话,软件就大了,三百多k的打包后都几兆了,而且用数据库的话又有问题,可能我经验不足吧。后来用vc写个小软件,一百多k,搞定。

中缀表达式转换原理:

①扫描表达式

②如果扫到的是数字,直接输出,如果扫描到的是运算符,这里只限于加减乘除和括号看步骤③

③如果是左括号,进栈,如果是右括号,将栈中从左括号开始的运算符都给弹出。如果是运算符。比较栈顶运算符和当前扫到的运算符的优先级。如果比栈顶的高,直接进栈

如果比栈顶的低,将栈顶弹出输出。将当前扫到的入栈。

自己在写的过程中也发现有些要注意的地方。里面实际上有很多东西要处理的。

当我们比较运算符的时候。要看当前栈顶的是不是运算符,如果是才能比,不是的话会是神马呢,唯有左括号和空栈。那我们就又要处理这个。

之前还写过一个判断是不是运算符的函数,后来删了。上面写的这些在代码上都有反应,我觉得看这些没意思,直接啃代码还好,我写的代码也没到啃的地步。写下只为自己以后要用或要找的时候可以看看,所以说,写博文就是记笔记的过程有木有,反正我碰到要查的东西如果blog有都在这找,自己写的有木有还不知道。

具体代码如下:欢迎指教

/*
*栈的应用——顺序栈实现简单进制转换
*后缀表达式求值
*将中缀表达式转换成后缀表达式
*/

#include <stdio.h>
#include <windows.h>
#include <math.h>
#define STACKSIZE 20

typedef char ElemType;
typedef struct Stack
{
int top;
ElemType element[STACKSIZE];
}*pStack;
pStack InitStack();
bool isStackEmpty(pStack);
void push(pStack,ElemType);
ElemType pop(pStack);
void Bin2Dec(pStack stack);
void Bin2Oct(pStack);
void After(pStack);
void ChangeToReversePolan(pStack);
bool isOperator(char);
int main()
{
pStack stack = InitStack();;
if(stack)
{
//Bin2Dec(stack);
//Bin2Oct(stack);
//After(stack);
ChangeToReversePolan(stack);
}
return 0;
}
/*-----------------------------顺序栈初始化-----------------------*/
pStack InitStack()
{
pStack stack = (pStack)malloc(sizeof(struct Stack));
if(stack)
{
stack->top = -1;
return stack;
}
return NULL;
}
/*------------------------------判断栈空--------------------------*/
bool isStackEmpty(pStack stack)
{
return stack->top==-1;
}
/*------------------------------判断栈满--------------------------*/
bool isStackFull(pStack stack)
{
return (stack->top==STACKSIZE-1);
}
/*--------------------------------压栈----------------------------*/
void push(pStack stack ,ElemType element)
{
if(!isStackFull(stack))
{
stack->top++;
stack->element[stack->top] = element;
}
else
printf("栈满\n");

}
/*--------------------------------弹栈----------------------------*/
ElemType pop(pStack stack)
{
int ret = stack->element[stack->top];
if(!isStackEmpty(stack))
{
stack->top--;
return ret;
}
else
printf("栈空\n");

}
/*-------------------------------遍历栈---------------------------*/
void travelStack(pStack stack)
{
int temp = stack->top;
while(stack->top>-1)
{
printf("%c->",stack->element[stack->top]);
stack->top--;
}
stack->top = temp;

}
/*---------------------------------进制转换-----------------------*/
//二进制转换成十进制
void Bin2Dec(pStack stack)
{
char source[20];
int i = 0;
int j = 0;
int sum = 0;
scanf("%c",&source[i]);
push(stack,source[i]);
while(source[i]!='#')
{
i++;
scanf("%c",&source[i]); //这就不判断栈是否满了
push(stack,source[i]);
}
//travelStack(stack);
pop(stack);
while(!isStackEmpty(stack))
{
sum = sum + (pop(stack)-48) *pow(2,j);
j++;
}
printf("%d\n",sum);

}
//二进制转换成八进制
void Bin2Oct(pStack stack)
{
//数据输入与进栈过程
char source[20];
int i = 0;
int j = 0;
int sum = 0;
int Result = 0;
scanf("%c",&source[i]);
push(stack,source[i]);
while(source[i]!='#')
{
i++;
scanf("%c",&source[i]); //这就不判断栈是否满了
push(stack,source[i]);
}
//travelStack(stack);
pop(stack);
while(!isStackEmpty(stack))
{
for(int k = 0; k<3; k++ )
{
if(!isStackEmpty(stack))
sum = sum + (pop(stack)-48) *pow(2,k);
}
Result = Result + sum * pow(10,j);
j++;
sum = 0;
}
printf("%d\n",Result);
}
/*-------------------------------表达式求值-------------------------------*/
//从简单的后缀表达式开始,再看中缀表达式和一元函数问题
//后缀表达式
void After(pStack stack)
{
char exp[50];
int i = 0;
int num1,num2;
printf("输入表达式(#结束):");
scanf("%c",&exp[i]);
while(exp[i] != '#')
{
i++;
scanf(" %c",&exp[i]);
}
//将数据输入和数据处理分开进行。
int j = 0;
while(j<i)
{
if( '0'<=exp[j] && '9'>=exp[j])
push(stack,exp[j]);
else
{
num2 = pop(stack);
num1 = pop(stack);
switch ( exp[j] )
{
case '+':push(stack,num1+num2-48);break;
case '-':push(stack,num1-num2+48);break;
case '*':push(stack ,(num1-48)*(num2-48)+48);break;
case '/':push(stack ,(num1-48)/(num2-48)+48);break;
default :printf("数据输入错误\n");return;
}
}
j++;
}
printf("%d\n",pop(stack)-48);
}
/*-------------------------------将中缀表达式转换成后缀表达式----------------------------*/
void ChangeToReversePolan(pStack stack)
{
char source[100];
int length,i = 0;
printf("输入中缀表达式:");
scanf("%s",source);
length = strlen(source);
printf("后缀表达式如下:");
//扫描
while(i <length) //1+2*3
{
//左括号处理,压栈
if(source[i] =='(')
push(stack,source[i]);
//右括号处理,弹栈输出到左括号
else if(source[i] ==')') //右括号处理
{
while(stack->element[stack->top] !='(')
{
printf("%c ",pop(stack));
}
pop(stack); //把最后的左括号搞掉
}
//运算符处理,比较运算符等级
else if( '*' == source[i] || '/' == source[i])
{
push(stack,source[i]);
}
else if( '+' == source[i] || '-' == source[i])
{
//还要判断栈顶是否是运算符,不是运算符就没有比较这个概念
if(stack->element[stack->top] == '(' || isStackEmpty(stack) )
push(stack,source[i]);
else
{
printf("%c ",pop(stack));
push(stack,source[i]);
}
}
else //如果需要,将数据和非法输入分开处理
{
printf("%c",source[i]);
if(source[i+1] >= '0' && source[i+1] <='9')
{
printf("%c ",source[i+1]);
i++;
}
else
printf(" ");
}

i++;
}
while(stack->top>=0)
{
printf("%c ",stack->element[stack->top]);
stack->top--;
}

printf("\n");
}


中缀表达式这也有点要注意的,不要超过三位数。本人 也就处理两位数而已,多了会有个空格的,运行就知道了。

假期第二天。估计今天起来算早的。^_^
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息