本文为数据结构之线性结构(堆栈),根据网课而整合的笔记。
计算机如何进行表达式求值?
-
表达式由两类对象构成:
- 运算数,如2、3、4
- 运算符号,如+、-、*、/
-
不同运算符号优先级不一样
后缀表达式
-
中缀表达式:运算符号位于两个运算数之间。如,a+b*c-d/e
-
后缀表达式:运算符号位于两个运算数之后。如,abc*+de/-
【例】62/3-42*+=?
后缀表达式求值策略
:从左向右“扫描”,逐个处理运算数和运算符号
1.遇到运算数怎么办?如何“记住”目前还不参与运算的数?
2.遇到运算符号怎么办?对应的运算数是什么?
启示:需要有种存储方法,能顺序存储算数,并在需要时“倒序”输出
堆栈的抽象数据类型描述
堆栈(Stack):具有一定操作约束的线性表
-
只在一堆(栈顶,Top)做插入、删除
-
插入数据:入栈(Push)
-
删除数据:出栈(Pop)
-
后入先出原则:Last In First Out(LIFO)
类型名称
:堆栈(Stack)
数据对象集
:一个有0或多个元素的有穷线性表。
操作集
:长度为MaxSize的堆栈S<-Stack,堆栈元素item<-ElementType
1.Stack CreateStack(int MaxSize): 生成空堆栈,其最大长度为MaxSize;
2.int IsFull(Stack S,int MaxSize):判断堆栈S是否已满;
3.void Push(Stack S,ElementType item):将元素item压入堆栈
4.int IsEmpty(Stack S):判断堆栈S是否为空;
5.ElementType Pop(Stack S):删除并返回栈顶元素;
ps:Push和Pop可以穿插交替进行;
例图:
栈的顺序存储实现
栈的顺序存储结构通常由一个一维数组和一个记录栈顶元素位置的变量组成。
#define MaxSize <储存数据元素的最大个数>
typedef struct SNode*Stack;
struct SNode{
ElementType Data[MaxSize];
int Top;
};
(1)入栈
void Push(Stack PtrS, ElementType item)
{
if(Ptrs->Top == MaxSize-1){
printf("堆栈满");
return;
}else{
PtrS->Data[++(PtrS->Top)]=item;
return;
}
}
(2)出栈
ElementType Pop(Stack Ptrs)
{
if(PtrS->Top==-1){
printf("堆栈空");
return ERROR;/*ERROR是ElementType的特殊值,标志错误*/
}else
return(PtrS->Data[(PtrS->Top)--]);
}
堆栈的链式存储实现
栈的链式存储结构实际上就是一个单链表,叫做链栈。插入和删除操作只能在链栈的栈顶进行。
typedef struct SNode*Stack;
struct SNode{
ElementType Data;
struct SNode *Next;
};
(1)堆栈初始化(建立空栈)
(2)判断堆栈s是否为空
Stack CreateStack()
{
/*构建一个堆栈的头结点,返回指针*/
Stack S;
S = (Stack)malloc(sizeof(struct SNode));
S->Next = NULL;
return S;
}
int IsEmpty(Stack S)
{
/*判断堆栈s是否为空,若为空函数返回整数1,否则返回0*/
return (S->Next == NULL);
}
void Push(ElementType item,Stack S)
{
/*将元素item压入堆栈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)
{
/*删除并返回堆栈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 TopElem;
}
}
堆栈应用
表达式求值:从左到右读入后缀表达式的各项(运算符或运算数)
1.运算数:入栈
2.运算符:从堆栈中弹出适当数量的运算数,计算并结果入栈;
3.最后,堆栈顶上的元素就是表达式的结果值。
中缀表达式求值
如何将中缀表达式转换为后缀表达式?
启示:
1.运算数相对顺序不变
2.运算符号顺序发生改变
- 需要存储“等待中”的运算符号(堆栈!)
- 要将当前运算符号与“等待中”的最后一个运算符号比较
方法:
从头到尾读取中缀表达式的每个对象,对不同对象按不同的情况处理。
- 运算数:直接输出;
- 左括号:压入堆栈;
- 右括号:将栈顶的运算符弹出并输出,直到遇到左括号(出栈,不输出);
- 运算符:
–若优先级大于栈顶运算符时,则把它压栈;
– 若优先级小于等于栈顶运算符时,将栈顶运算符弹出并输出;再比较新的栈顶运算符,直到该UN算符大于栈顶运算符优先级为止,然后将改运算符压栈; - 若各对象处理完毕,则把堆栈中存留的运算符一并输出。
实例:
其他应用:
- 函数调用及递归实现
- 深度优先搜素
- 回溯算法
- 。。。
声明:部分资料源自网络,如有侵权,请联系我删除!
文中如存在谬误、混淆等不足,欢迎批评指正!