先了解下后缀表达式和中缀表达式
后缀表达式:运算符号位于两个运算数之后,如 a b c * + d e / -
其对应的中缀表达式为 a + b * c - d / e
堆栈(Stack):具有一定操作约束的线性表,只在一端(栈顶,Top)做插入和删除操作
插入数据:入栈(Push)
删除数据:出战(Pop)
特点:后入先出:Last in First Out(LFO)
栈的顺序存储结构通常由一个一维数组和一个记录栈顶元素位置的变量组成
#define Maxsize <存储数据元素的最大个数>
typedef struct SNode *Stack;
struct SNode{
ElementType Data[Maxsize];
int Top;
};
与栈相关的操作:
一、入栈和出栈
//入栈操作
void Push(Stack Ptrs,ElementType item){
if(Ptrs -> Top == Maxsize - 1){
printf("栈满");
return;
}
else{
Ptrs -> Data[++(Ptrs -> Top)] = item;
return ;
}
}
//出栈操作
ElementType Pop(Stack Ptrs){
if(Ptrs -> Top == -1){
printf("栈空");
return error;
}
else
return (Ptrs -> Data[(Ptrs -> Top)--]);
}
如何利用一个数组实现两个堆栈?要求高效的利用空间。
答:使两个栈分别从数组的两头开始向中间生长,当两个栈的栈顶指针相遇,表示两个栈都满了
#define Maxsize <存储数据元素的最大个数>
struct DStack{
ElementType Data[Maxsize];
int Top1;
int Top2;
}S;
S.Top1 = -1;
S.Top2 = Maxsize;
//入栈
void Push(struct DStack *Ptrs,ElementType item,int Tag){
if(Ptrs -> Top2 - Ptrs -> Top1 == 1){
printf("栈满");
return ;
}
if(Tag == 1){
Ptrs -> Data[++(Ptrs -> Top1)] = item;
}
else{
Ptrs -> Data[--(Ptrs -> Top2)] = item;
}
//出栈操作
ElementType Pop(strut DStack * Ptrs,int Tag)}
if(Tag == 1){
if(Ptrs -> Top1 == -1){
printf("栈空");
return NULL;
}
else
return Ptrs -> Data[(Ptrs -> Top1)--];
}
else{
if(Ptrs -> Top2 == Maxsize){
printf("栈空");
return NULL;
}
else{
return Ptrs -> Data[(Ptrs -> Top2)++];
}
}
}
堆栈的链式存储实现:栈的链式存储结构实际上是一个单链表,叫做链栈,插入和删除操作只能再链栈的栈顶进行,栈顶指针Top应该在链表头部,便于插入和删除。
typedef struct SNode * Stack;
struct SNode{
ElementType Data;
struct SNode * Next;
};
Stack CreateStack(){
Stack S;
S = (Stack)malloc(sizeof(Struct SNode));
S -> Next = NULL;
return S;
}
int IsEmpty(Stack S){
return S -> Next == NULL;
}
入栈和出栈操作:
void Push(ElementType item,Stack S){
struct SNode *TmpCell;
TmpCell = (struct SNode *)malloc(sizeof(struct SNode));
TmpCell -> Element = item;
TmpCell -> Next = S -> Next;
S -> Next = TmpCell;
}
ElementType Pop(Stack S){
struct SNode * FirstCell;
ElementType TopElem;
if(IsEmpty(s)){
printf("栈空");
return NULL;
}
else{
FirstCell = S -> Next;
S -> Next = FirstCell -> Next;
TopElem = FirstCell -> Element;
free(FirstCell);
return(FirstCell);
}
}
堆栈的应用:中缀表达式求值
基本策略:中缀转后缀然后求值
1.运算数相对顺序不变
2.运算符号顺序发送改变
*需要存储等待中的运算符号
*要将当前运算符号与等待中最后一个运算符号比较,如果前一个运算符优先高,则它出栈,用于计算。
➢从头到尾读取中缀表达式的每个对象,对不同对象按不同的情况处理。
①运算数:直接输出;
②左括号:压入堆栈:
③右括号:将栈顶的运算符弹出并输出,直到遇到左括号(出栈,不输出) ;
④运算符:
若优先级大于栈顶运算符时,则把它压栈;
若优先级小于等于栈项运算符时,将栈顶运算符弹出并输出:再比
较新的栈顶运算符,直到该运算符大于栈顶运算符优先级为止,然
后将该运算符压栈;
⑤若各对象处理完毕,则把堆栈中存留的运算符一-并输出。