数据结构基础2:栈
求算术表达式有两种方法:
1.运算符优先级法:该方法来自严蔚敏版数据结构,需要设置两个栈,一个操作数栈,一个操作符栈。
2.后缀表达式法:中缀表达式转后缀表达式(逆波兰式)并求值,分为两个过程,每个过程个需要一个栈。
本文采用后缀表达式法求算术表达式:中缀表达式转后缀表达式的思路大体是判断当前运算符是否比上一个运算符优先级高。
如果高则将当前运算符push压入栈中;如果低,则将上一个运算符pop出来,即把前面的运算当成一个整体先列出来。
main.c
#include <stdio.h>
#include <string.h>
#include "Stack.h"
/* 中缀表达式转后缀表达式(逆波兰式)并求值 */
char optrset[6] = {'+','-','*','/','(',')'};
char cmpset[6][6] = {/* + - * / ( ) */
/* + */ '<', '<', '>', '>', '>', '<',
/* - */ '<', '<', '>', '>', '>', '<',
/* * */ '<', '<', '<', '<', '>', '<',
/* / */ '<', '<', '<', '<', '>', '<',
/* ( */ '>', '>', '>', '>', ' ', '=',
/* ) */ ' ', ' ', ' ', ' ', ' ', ' '};
/*求操作符序号*/
int OrderOptr(char c)
{
int i;
for(i = 0; i < sizeof(optrset); i++) {
if(c == optrset[i])
return i;
}
}
/* 操作符比较 */
char CmpOptr(char a, char b)
{
return cmpset[OrderOptr(a)][OrderOptr(b)];
}
/* 判断是否为操作符 */
int IsOptr(char c)
{
int i;
for(i = 0; i < sizeof(optrset); i++) {
if(c == optrset[i])
return 1;
}
return 0;
}
/*运算*/
char CalOptr(char lv, char rv, char optr)
{
char res_c;
int l = 0, r = 0, res = 0;
l = lv - '0';
r = rv - '0';
switch(optr) {
case '+':
res = l + r;
break;
case '-':
res = l - r;
break;
case '*':
res = l * r;
break;
case '/':
res = l / r;
break;
default:
break;
}
res_c = res + '0';
return res_c;
}
int main(int argc, char *argv[])
{
SPtr stack = NULL;
char str[20] = {'\0'};
char cstr[2] = " ", dstr[2] = " ";
char c, d;
char result;
char lvalue, rvalue;
int i = 0;
stack = CreatStack();
c = getchar();
cstr[0] = c;
/* 中缀表达式转后缀表达式 */
while(c != '\n') {
if(!IsOptr(c)) {
cstr[0] = c;
strcat(str, cstr);
c = getchar();
}
else {
if(StackEmpty(stack)) {
result = '>';
}
else {
GetTop(stack, &d);
result = CmpOptr(d, c);
}
switch(result) {
case '>':
Push(stack, c);
c = getchar();
break;
case '=':
Pop(stack, &d);
c = getchar();
break;
case '<':
Pop(stack, &d);
dstr[0] = d;
strcat(str, dstr);
break;
default:
break;
}
}
}
while(!StackEmpty(stack)) {
Pop(stack, &d);
dstr[0] = d;
strcat(str, dstr);
}
printf("%s\n", str);
/* 后缀表达式求值 */
while(str[i] != '\0') {
if(!IsOptr(str[i]))
Push(stack, str[i]);
else {
Pop(stack, &rvalue);
Pop(stack, &lvalue);
Push(stack, CalOptr(lvalue, rvalue, str[i]));
}
i++;
}
Pop(stack, &d);
printf("The result is %c\n", d);
ClearStack(stack);
DestroyStack(stack);
printf("Press enter to continue ...");
getchar();
return 0;
}
Stack.c
#include "Stack.h"
SPtr CreatStack()
{
SPtr sp = malloc(sizeof(struct LinkStack));
if(!sp)
return NULL;
sp->base = malloc(sizeof(struct SElemType));
sp->base->next = NULL;
sp->top = sp->base;
sp->stacksize = 0;
return sp;
}
int StackEmpty(SPtr sp)
{
if(!sp)
return ERROR;
if(sp->stacksize == 0)
return 1;
else
return 0;
}
int StackLength(SPtr sp)
{
if(!sp)
return ERROR;
return sp->stacksize;
}
int GetTop(SPtr sp, ElemType *x)
{
if(!sp)
return ERROR;
*x = sp->top->next->value;
return OK;
}
int Push(SPtr sp, ElemType x)
{
SElemPtr pushnode;
if(!sp)
return ERROR;
sp->top->value = x;
pushnode = malloc(sizeof(struct SElemType));
pushnode->next = sp->top;
sp->top = pushnode;
sp->stacksize++;
return OK;
}
int Pop(SPtr sp, ElemType *x)
{
SElemPtr popnode;
if(!sp)
return ERROR;
if(sp->top == sp->base)
return ERROR;
popnode = sp->top->next;
free(sp->top);
sp->top = popnode;
*x = sp->top->value;
sp->stacksize--;
return OK;
}
int StackTraverse(SPtr sp)
{
int i;
SElemPtr tmpnode;
if(!sp)
return ERROR;
tmpnode = sp->top->next;
for(i = 0; i < sp->stacksize; i++) {
printf("%c ", tmpnode->value);
tmpnode = tmpnode->next;
}
printf("\n");
return OK;
}
int ClearStack(SPtr sp)
{
int i;
SElemPtr tmpnode;
if(!sp)
return ERROR;
tmpnode = sp->top->next;
for(i = 0; i < sp->stacksize; i++) {
tmpnode->value = '\0';
tmpnode = tmpnode->next;
}
sp->top = sp->base;
sp->stacksize = 0;
return OK;
}
int DestroyStack(SPtr sp)
{
SElemPtr tmpnode = sp->top, storenode = NULL;
if(!sp)
return ERROR;
while(tmpnode != sp->base) {
storenode = tmpnode->next;
free(tmpnode);
tmpnode = storenode;
}
free(tmpnode);
free(sp);
return OK;
}
Stack.h
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#define ERROR -1
#define OK 0
#define ElemType char
typedef struct SElemType{
ElemType value;
struct SElemType *next;
} *SElemPtr;
typedef struct LinkStack{
SElemPtr base;
SElemPtr top;
int stacksize;
} *SPtr;
SPtr CreatStack();
int StackEmpty(SPtr sp);
int StackLength(SPtr sp);
int GetTop(SPtr sp, ElemType *x);
int Push(SPtr sp, ElemType x);
int Pop(SPtr sp, ElemType *x);
int StackTraverse(SPtr sp);
int ClearStack(SPtr sp);
int DestroyStack(SPtr sp);