一,条件及要求
1,表达式必须是合法的
2,表达式必须遵循普通的优先级法则
3,默认运算符为 * 、 + 、 ( 、 )、-
二,对后序(后缀)表达式的理解
后序表达式本质上讲:想象一个栈空间,对于一个后序表达式,如果读到数字,则入栈,如果读到运算符,则从栈顶取出两个元素用该运算符进行计算,并将计算结果压入栈,重复该步骤直到表达式读取完毕。
三,分析
eg: 中序表达式 a+b 其后序表达式为: a b +
中序 a + b * c 后序表达式为: a b c * +
中序 a + b * c + d 后序表达式为: a b c * + d +
中序 a + b * c + d * e 后序表达式为: a b c * + d e * +
我们肯定要用到栈。如果读到操作数则直接输出,如果读到操作符则应该入栈。
当读到一个操作数的时候,立即把它放到输出中。操作数不立即输出,所以必须先存在某个地方中,正确的做法是将所有见过的操作符放在栈中,当遇到左圆括号时我们也要将其入栈。我们从空栈开始计算。
如果见到有括号,那么就将栈中元素弹出直到遇见一个左括号,这个左括号只弹出而不输出。
如果见到其他的运算符,那么我们从栈中弹出栈元素直到发现优先级更低的元素为止。(就是要求栈顶的操作符的优先级必须比上一个元素的优先级要高,括号除外)。
注意,+ 的优先级最低,( 的优先级最高
最后如果读到了输入的末尾,我们将栈元素弹出直到该栈变为空栈
说不清楚,寄
四,代码实现
1,创建结构体,用数组模拟栈
#include<stdio.h>
#include<stdlib.h>
#define MaxStackSize (20) //栈最大容量
#define EmtpyInStack (-1) //栈空时,栈顶所在位置
struct StackRecord {
int Capacity; //容量
int TopOfStack; //栈顶位置
char* Array; //栈空间
};
typedef struct StackRecord *Stack;
2,需要对栈进行初始化
Stack CreatStack(int SizeOfstack) //创建栈空间,并且初始化
{
Stack s = malloc(sizeof(struct StackRecord));
if (s == NULL)
{
printf("error in create stack");
exit(0);
}
s->Array = malloc(sizeof(char) * SizeOfstack);
if (s->Array == NULL)
{
printf("error in create array in stack");
exit(0);
}
s->Capacity = SizeOfstack;
s->TopOfStack = EmtpyInStack;
}
3,我们应该还要注意到,在表达式中的操作数应该最好是字母,这样我们可以把表达式存入字符数组从而来每次只读一个字符进行操作,如果由数字组成,读取时会比较麻烦。
4,总体代码如下
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#define MaxStackSize (20) //栈最大容量
#define EmtpyInStack (-1) //栈空时,栈顶所在位置
struct StackRecord {
int Capacity; //容量
int TopOfStack; //栈顶位置
char* Array; //栈空间
};
typedef struct StackRecord *Stack;
Stack CreatStack(int SizeOfstack) //创建栈空间,并且初始化
{
Stack s = malloc(sizeof(struct StackRecord));
if (s == NULL)
{
printf("error in create stack");
exit(0);
}
s->Array = malloc(sizeof(char) * SizeOfstack);
if (s->Array == NULL)
{
printf("error in create array in stack");
exit(0);
}
s->Capacity = SizeOfstack;
s->TopOfStack = EmtpyInStack;
}
int JudgeEmpty(Stack s)
//判断是否栈空
{
return s->TopOfStack == EmtpyInStack;
}
//弹出栈
char GetOutStack(Stack s)
{
if (JudgeEmpty(s))
{
printf("表达式错误,存在栈为空的情况");
exit(0);
}
//s->TopOfStack--;
return s->Array[s->TopOfStack--];
}
int JudgeFullStack(Stack s)
{
return s->TopOfStack + 1 == s->Capacity;
}
void GetInStack(char a, Stack s)
//压入栈
{
if (JudgeFullStack(s))
{
printf("表达式错误,导致出现栈满");
exit(0);
}
s->TopOfStack++;
s->Array[s->TopOfStack] = a;
}
int main()
{
int i;
//创建链表
Stack s = CreatStack(MaxStackSize);
char arr[20] = { 0 };
gets(arr);
for (i = 0; arr[i] != '\0'; i++)
{
if(arr[i] >= 'a' && arr[i] <= 'z')
{
printf("%c", arr[i]);
}
//如果此时栈顶的元素的优先级比读入的低,则可以进去
//如果此时栈顶元素的优先级和读入的相等,也应该输出。
else if (arr[i] == '+'||arr[i]=='-')
{
if (JudgeEmpty(s) == 0) {//不为空,则判断是否需要弹出栈
while (s->Array[s->TopOfStack] != '(')
{
char out = GetOutStack(s);
printf("%c", out);
if (JudgeEmpty(s))
{
break;
}
}
}
GetInStack(arr[i], s);//入
}
else if (arr[i] == '*'||arr[i]=='/')
//这两个运算符的优先级是相同的
{
if (JudgeEmpty(s) == 0) {
while (s->Array[s->TopOfStack] != '+' &&
s->Array[s->TopOfStack] != '('&&s->Array[s->TopOfStack]!='-')
{
char out = GetOutStack(s);
printf("%c", out);
if (JudgeEmpty(s))
{
break;
}
}
}
GetInStack(arr[i], s);
}
else if (arr[i] == '(')
//无条件入栈。优先级最高
{
GetInStack(arr[i], s);
}
else if(arr[i]==')')
//找到对应的(,并且不用输出
{
char out = GetOutStack(s);
while (out != '(')
{
printf("%c", out);
out = GetOutStack(s);
}
}
}
//将栈弹空
while (JudgeEmpty(s) == 0)
{
printf("%c", GetOutStack(s));
}
return 0;
}
这里,,用字母代表数字,,感觉有点lou,,,可以改进一下,用数字,因为这里不需要用到计算,优化还是比较方便的。。
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#define MaxStackSize (20) //栈最大容量
#define EmtpyInStack (-1) //栈空时,栈顶所在位置
struct StackRecord {
int Capacity; //容量
int TopOfStack; //栈顶位置
char* Array; //栈空间
};
typedef struct StackRecord *Stack;
Stack CreatStack(int SizeOfstack) //创建栈空间,并且初始化
{
Stack s = malloc(sizeof(struct StackRecord));
if (s == NULL)
{
printf("error in create stack");
exit(0);
}
s->Array = malloc(sizeof(char) * SizeOfstack);
if (s->Array == NULL)
{
printf("error in create array in stack");
exit(0);
}
s->Capacity = SizeOfstack;
s->TopOfStack = EmtpyInStack;
}
int JudgeEmpty(Stack s)
//判断是否栈空
{
return s->TopOfStack == EmtpyInStack;
}
//弹出栈
char GetOutStack(Stack s)
{
if (JudgeEmpty(s))
{
printf("表达式错误,存在栈为空的情况");
exit(0);
}
//s->TopOfStack--;
return s->Array[s->TopOfStack--];
}
int JudgeFullStack(Stack s)
{
return s->TopOfStack + 1 == s->Capacity;
}
void GetInStack(char a, Stack s)
//压入栈
{
if (JudgeFullStack(s))
{
printf("表达式错误,导致出现栈满");
exit(0);
}
s->TopOfStack++;
s->Array[s->TopOfStack] = a;
}
int main()
{
int i;
//创建链表
Stack s = CreatStack(MaxStackSize);
char arr[30] = { 0 };
gets(arr);
for (i = 0; arr[i] != '\0'; )
{
int judg = 0;
while((arr[i] >= '0' && arr[i] <= '9')||(arr[i]=='.'))
{
judg = 1;
printf("%c", arr[i]);
i++;
}
if(judg==1)
printf(" ");
//如果此时栈顶的元素的优先级比读入的低,则可以进去
//如果此时栈顶元素的优先级和读入的相等,也应该输出。
if (arr[i] == '+'||arr[i]=='-')
{
if (JudgeEmpty(s) == 0) {//不为空,则判断是否需要弹出栈
while (s->Array[s->TopOfStack] != '(')
{
char out = GetOutStack(s);
printf("%c ", out);
if (JudgeEmpty(s))
{
break;
}
}
}
GetInStack(arr[i], s);//入
}
else if (arr[i] == '*'||arr[i]=='/')
//这两个运算符的优先级是相同的
{
if (JudgeEmpty(s) == 0) {
while (s->Array[s->TopOfStack] != '+' &&
s->Array[s->TopOfStack] != '('&&s->Array[s->TopOfStack]!='-')
{
char out = GetOutStack(s);
printf("%c ", out);
if (JudgeEmpty(s))
{
break;
}
}
}
GetInStack(arr[i], s);
}
else if (arr[i] == '(')
//无条件入栈。优先级最高
{
GetInStack(arr[i], s);
}
else if(arr[i]==')')
//找到对应的(,并且不用输出
{
char out = GetOutStack(s);
while (out != '(')
{
printf("%c ", out);
out = GetOutStack(s);
}
}
i++;
}
//将栈弹空
while (JudgeEmpty(s) == 0)
{
printf("%c ", GetOutStack(s));
}
return 0;
}