2.2.1什么是堆栈
例子:计算机如何进行表达式求值
主要问题:运算符号存在优先级
定义理解:
后缀表达式求值策略:从左向右“扫描”,逐个处理运算符和运算符号。
碰到运算数先记住
碰到运算符号就把最近的两个运算数拿来做运算
启示:需要有种存储方法,能顺序运算存储数,并在需要时“倒序”输出!
即:先放进的后出,后放的先出
堆栈的抽象数据类型描述
堆栈Stack:具有一定操作约束的线性表。
只在栈顶做插入和删除。
插入数据:入栈Push
删除数据:出栈Pop
后入先出:Last in First Out
2.2.2堆栈的顺序存储实现
栈的顺序存储实现通常由一个一维数组和一个记录栈顶元素位置的变量组成。
实现:
#define MAXSIZE 1000//存储元素的最大个数,随意设置
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;
(Ptrs->Top)++;//更新栈顶
Ptrs->Data[Ptrs->top]=item;//元素赋值
}
}
出栈
ElementType Pop(Stack Ptrs)
{
if(Ptrs->Top==-1){//栈空
printf("堆栈空");
return ERROR;//ERROR是ElementType的特殊值,标志错误
}else{
(Ptrs->Top)--;
return Ptrs->Data[Ptrs->Top];
}
}
例题
最佳生长方式:从两边向中间生长
好处:只要数组有空间就能够入栈,充分利用空间
当两个栈顶指针相遇时,代表栈满
2.2.3堆栈的链式存储实现
栈的链式存储结构实际上就是一个单链表,叫做链栈。插入和删除操作只能在链栈的栈顶进行。
栈顶指针要在头结点的那一头。
实现:
typedef struct SNode* Stack;
struct SNode{
ElemnetType Data;
struct SNode* Next;
};
相应操作:
建立空栈
Stack CreateStack()
{
Stack S;
S=(Stack)malloc(sizeof(struct SNode));
S->Next=NULL;
return S;
}
理解,其实是创建一个图中结构
添加元素是进行相应入栈即可。
2.判断是否栈空
int IsEmpty(Stack S)
{
return (S->Next==NULL);//判断语句与return合并
}
3.入栈
void Push(ElementType item,Stack S)
{
struct SNode* tmpcell;
tmpcell=(struct Snode*)malloc(sizeof(struct SNode));
tmpcell->Data=item;
tmpcell->Next=S->Next;
S->Next=tmpcell;
}
4.出栈
ElmentType Pop(Stack S)//删除并返回栈顶元素
{
struct SNode* firstcell;//被删节点
ElementType topelm;
if(IsEmpty(S))
{
printf("栈空");
return NULL;
}else{
firstcell=S->Next;//赋值
S->Next=firstcell->Next;
topelm=firstcell->Data;
free(firstcell);
return topelm;
}
}
2.2.4堆栈应用:表达式求值
注重理解:当后一个运算符优先级比当前的低时,才能输出当前运算符。
总结:
例子:
堆栈的其他应用:(可以深度理解以下操作的本质
函数调用及递归实现
深度优先搜索
回溯算法
……