链栈+后缀表达式求值算法,借用我自己上次C语言写的链栈,详细实现代码如下:
头文件C_Stack.h:
/*C_Stack.h*/
#ifndef C_STACK_H_INCLUDED
#define C_STACK_H_INCLUDED
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <stdbool.h>
#include <math.h>
#include <time.h>
#include <windows.h>
typedef struct Stack
{
int Data;
struct Stack *Next;
}LStack,*PStack;
typedef struct Position
{
struct Stack *PTop;
struct Stack *PBattom;
}LPosition,*PPosition;
PPosition InitiateStack(PPosition P);/*初始化栈*/
bool Push(PPosition P,int Value);/*压栈*/
bool Pop(PPosition P,int *Tmp);/*弹栈*/
int Top(PPosition P);/*返回栈顶元素*/
void Display(PPosition P);
void ClearStack(PPosition P);/*清空栈*/
bool EmptyStack(PPosition P);/*判断栈是否为空*/
int StackSize(PPosition P);/*求栈所含元素的多少*/
#endif // C_STACK_H_INCLUDED
源代码C_Stack.c:
/*C_Stack.c*/
#include "C_Stack.h"
PPosition InitiateStack(PPosition P)
{
P->PTop = (struct Stack*)malloc(sizeof(struct Stack));/*相当于申请一个新结点*/
if(!(P->PTop))/*申请不成功。养成良好的习惯,最好预先判断;万一哪天一个不小心内存泄漏了,哦嚯!*/
/*return false;*/
{
printf("Initiate failed.\n");
exit(EXIT_FAILURE);
}
P->PBattom = P->PTop;/*栈底指向栈顶*/
/*
上面这句话我原来写作:
P->PTop = P->PBattom;
查了很长时间才发现问题是:
很丢人,没有初始化的指针就拿来赋值
*/
P->PTop->Next = NULL;/*栈顶指针置为空*/
/*return true;初始化成功*/
return P;
}
bool Push(PPosition P,int value)
{
LStack *PNew = (LStack *)malloc(sizeof(LStack));/*相当于申请一个新结点*/
if(!PNew)/*申请不成功,压栈失败。养成良好的习惯,最好预先判断;万一哪天一个不小心内存泄漏了,哦嚯!*/
return false;
PNew->Data = value;/*数值赋給值域*/
PNew->Next = P->PTop;/*新结点的指针域指向栈顶*/
P->PTop = PNew;/*新结点成为新的栈顶*/
return true;/*压栈成功*/
}
bool Pop(PPosition P,int *Tmp)
{
/*LStack *PTmp = NULL;申请一个新结点,赋值为空*/
LPosition *LPTmp = (LPosition *)malloc(sizeof(LPosition));/*开辟一段空间給新结点*/
if(P->PTop->Next == NULL)/*栈顶指针为空说明栈为空*/
return false;/*弹栈失败*/
LPTmp = P;/*为什么创建这个临时结点,刁肥宅自己也不清楚,习惯吧*/
*Tmp = LPTmp->PTop->Data;
LPTmp->PTop = LPTmp->PTop->Next;/*栈顶的下一栈元素的指针指向栈顶*/
free(P);/*弹栈后释放空间*/
return true;/*弹栈成功*/
}
int Top(PPosition P)
{
LStack *PTmp = P->PTop;/*新建栈指针指向栈顶*/
/*printf("%d\n",PTmp->Data);*/
return PTmp->Data; /*返回栈顶元素 */
}
void Display(PPosition P)
{
LStack *Tmp = P->PTop;/*新建栈指针指向栈顶*/
int Line = 0;/*统计已结点个数*/
while(Tmp->Next != NULL)/*当栈顶指针不为空时*/
{
printf("%-6d",Tmp->Data);/*打印栈顶元素*/
Line ++;
if(Line % 10 == 0)
printf("\n");/*每行打印10个元素*/
Tmp = Tmp->Next;/*使栈顶的下一栈元素的指针指向栈顶*/
}
}
void ClearStack(PPosition P)
{
LPosition *PTmp = (LPosition *)malloc(sizeof(LPosition));/*创建临时位置指针*/
while(P->PTop->Next != NULL)/*当栈顶指针不为空时*/
{
PTmp = P;/*栈顶位置指针赋給临时位置指针*/
P->PTop = P->PTop->Next;/*使栈顶的下一栈元素的指针指向栈顶*/
free(P);/*释放当前栈顶元素的空间*/
}
}
bool EmptyStack(PPosition P)
{
return P->PTop->Next == NULL;/*当栈为空时,这句话为真,函数返回true;
当栈非空时,这句话为假,函数返回false*/
}
int StackSize(PPosition P)
{
LPosition *PTmp = (LPosition *)malloc(sizeof(LPosition));/*创建临时位置指针*/
//LStack *STmp = P->PTop;
PTmp = P;/*栈顶指针赋給临时位置指针*/
int ID = 0;/*初始化计数变量为0*/
while(PTmp->PTop->Next != NULL)/*当现在的栈顶元素指针不为空时,执行循环体*/
{
PTmp->PTop = PTmp->PTop->Next;/*使栈顶的下一栈元素的指针指向栈顶*/
ID ++;/*计数加一*/
}
return ID;/*返回栈元素的个数*/
}
源代码test.c:
/*test.c*/
#include "C_Stack.h"
bool DoOperator(PPosition P,char Operator);
int main()
{
LPosition *P = (LPosition *)malloc(sizeof(LPosition));
/*上面这句话直接写成:
LPosition *P = NULL;
会报错,为什么?指针置空,而后指向初始化后栈的首地址,不对吗?
*/
P = InitiateStack(P);
char Array[] = "5964-*+93/-#";
int i = 0,Ans = 0;
printf("所计算的中缀表达式为:%s\n",Array);
char Ch = Array[i ++];
while(Ch != '#')
{
if(Ch >= '0' && Ch <= '9')
if( Push( P,(int)(Ch - 48) ) )
;
else if(Ch == '+' || Ch == '-' || Ch == '*' || Ch == '/')
{
if(!DoOperator(P,Ch))
{
printf("运算出错!\n");
exit(EXIT_FAILURE);
}
}
else
{
printf("键入了非法字符,请重新输入!\n");
exit(EXIT_FAILURE);
}
Ch = Array[i ++];
}
Ans = Top(P);
printf("Ans = %d.\n栈中内容为:\n",Ans);
Display(P);
ClearStack(P);
return 0;
}
bool DoOperator(PPosition P,char Operator)
{
int Left = -1,Rigth = -1;
if(EmptyStack(P))
{
printf("缺少右操作数\n");
return false;
}
/*rigth = Top(P);*/
if(Pop(P,&Rigth))
;
else
{
printf("缺少左操作数\n");
return false;
}
if(Pop(P,&Left))
;
else
{
printf("缺少左操作数\n");
return false;
}
switch(Operator)
{
case '+':
if(Push(P,Left + Rigth))
;
break;
case '-':
if(Push(P,Left - Rigth))
;
break;
case '*':
if(Push(P,Left * Rigth))
;
break;
case '/':
if(fabs ( (double) Rigth ) )
{
printf("Divided by 0.\n");
return false;
}
else
{
if(Push(P,Left / Rigth))
;
}
break;
default:
return false;
}
return true;
}
代码成功编译后的运行结果如图所示: