关于栈
本周系统的学习了栈, 关于栈, 我看过一个很形象的描述, 有一群人被追到一个窄巷子里, 这个窄巷子只能允许一人通过, 里面的人要想出来, 必须后面的人先出来, 即遵循先入后出的规则, 这就是栈,类似的概念还有队列,他遵循先入先出的规则, 这里不多做介绍。
表达式求值
首先是表达式求值中要用到的栈的基本操作
- 创建一个链栈, 包含数据和下一个元素地址
typedef struct LinkList
{
char operatorAndData;
struct LinkList *next;
}LinkList,*LinkNode;
- 栈的基本属性, 包括栈顶和元素个数
typedef struct LinkStact
{
LinkNode top;
int count;
}LinkStack;
- 创建链栈(栈是一个没有头结点的单链表)
State createStack(LinkStack *S) {
S->count = -1;
S->top = NULL;
return OK;
}
- 入栈操作(push)
State pushStack(LinkStack *S, char data) {
LinkNode s;
s = (LinkNode)malloc(sizeof(LinkList));
s->operatorAndData = data;
s->next = S->top;
S->top = s;
S->count++;
return OK;
}
- 出栈操作(pop)
State popStack(LinkStack *S,char *data) {
LinkNode p;
//判断栈空
if (S->top == NULL || S->count==-1) {
return ERROR;
}
*data = S->top->operatorAndData;
p = S->top;
S->top = S->top->next;
S->count--;
free(p);
return OK;
}
主函数中进行的操作, 包括表达式的输入, 中缀转后缀操作等
- 中缀转后缀
while (inExpression[i]!='\0') {
if (inExpression[i]<48 || inExpression[i]>57) {
if (inExpression[i] == 41) {
if (!(infixExpression.count < 0)) {
popStack(&infixExpression, &postTmp);
while (postTmp != 40) {
postfixExpression[j++] = postTmp;
if (!(infixExpression.count < 0))
popStack(&infixExpression, &postTmp);
else
break;
}
}
}
else if (inExpression[i] == 43 || inExpression[i] == 45 ) {
if (!(infixExpression.count < 0)) {
popStack(&infixExpression, &postTmp);
while (postTmp == 42 || postTmp == 47) {
postfixExpression[j++] = postTmp;
if (!(infixExpression.count < 0)) {
popStack(&infixExpression, &postTmp);
}
else
break;
}
pushStack(&infixExpression, postTmp);
}
pushStack(&infixExpression, inExpression[i]);
}
else {
pushStack(&infixExpression, inExpression[i]);
}
}
else {
postfixExpression[j++] = inExpression[i];
}
i++;
}
while (!(infixExpression.count < 0)) {
popStack(&infixExpression, &postTmp);
postfixExpression[j++] = postTmp;
}
- 转化完成后, 求值
//计算后缀表达式
i = 0;
while (i != j) {
if (postfixExpression[i]<48 || postfixExpression[i]>57) {
popStack(&computeStack, &operatorData1);
popStack(&computeStack, &operatorData2);
if (postfixExpression[i] == 43) {
postTmp = (operatorData2-48 + operatorData1-48)+48;
pushStack(&computeStack, postTmp);
}
if (postfixExpression[i] == 45) {
postTmp = (operatorData2 - 48) -
(operatorData1 - 48) + 48;
pushStack(&computeStack, postTmp);
}
if (postfixExpression[i] == 42){
postTmp = (operatorData2 - 48) *
(operatorData1 - 48) + 48;
pushStack(&computeStack, postTmp);
}
if (postfixExpression[i] == 47) {
postTmp = (operatorData2 - 48) /
(operatorData1 - 48) + 48;
pushStack(&computeStack, postTmp);
}
}
else
pushStack(&computeStack, postfixExpression[i]);
i++;
}
popStack(&computeStack, &result);
printf("%c\n", result);
return OK;
}
关于中缀转后缀
中缀转后缀是表达式求值的一种算法, 为了把人能看懂的语言转化为机器能看懂的语言, 然后写算法, 让机器运算。
遵循的规则
- 遇到操作数:添加到后缀表达式中或直接输出
- 栈空时:遇到运算符,直接入栈
遇到左括号:将其入栈
遇到右括号:执行出栈操作,输出到后缀表达式,直到弹出的是左括号
注意:左括号不输出到后缀表达式 - 遇到其他运算符:弹出所有优先级大于或等于该运算符的栈顶元素,然后将该运算符入栈
- 将栈中剩余内容依次弹出后缀表达式