2.3堆栈
2.3.1堆栈的定义
引:
问题——电脑计算复杂顺序算术式的优先级
- 中缀表达式:5+6/2-3*4
- 后缀表达式(栈):5 6 2 / + 3 4 *-
- 算法:当连续出现数字时,记住这个数字序列,遇到符号时取出离符号最近的两个数字运算,重复这个过程
- 实现:管理一个序列,对该序列的主要操作是在序列的末尾插入元素和删除(取出)元素。
堆栈(Stack)
- 定义:
可以认为是具有一定约束的线性表,插入和删除操作都作用在一个称为栈顶(Top)的位置。 - 特性:
数据插入(Push):压入栈;
数据删除(Pop):弹出栈;
后入先出(Last In First Out,LIFO)。 - 数据对象集
一个有0个或者多个元素的有穷线性表。 - 操作集
(1)Stack CreatStack(int MaxSize):生成空栈,最大长度为MaxSize;
(2)bool IsFull(Stack S):判断栈是否已经堆满
(3)void Push(Stack S, ElementType X):将元素押入栈内
(4)bool IsEmpty(Stack S):判断栈是否为空,是返回1否则0
(5)ElementType Pop(Stack S):删除并且返回栈顶元素。若堆栈为空,返回错误信息,否则将栈顶数据元素从堆栈中删除并返回
2.3.2堆栈的实现
1.栈的顺序存储实现
- 描述栈类型(Stack)
typedef int Position;
typedef struct SNode*PtrToSNode;
struct SNode{
ElementType * Data;/*存储元素的数组*/
Position Top;/*栈顶指针*/
int MaxSize;/*堆栈最大容量*/
};
typedef PtrToSNode Stack;
- 顺序栈的创建
Stack CreatStack(int MaxSize)
{
Stack S=(Stack)malloc(sizeof(struct SNode));
S->Data=(ElementType*)malloc(MaxSize*sizeof(ElementType));
S->Top=-1;
S->MaxSize=MaxSize;
return S;
}
- 入栈
void Push(Stack PtrS, ElementType item)
{
if(PtrS->Top==MAXSIZE-1){
printf("栈堆满");
return;
}
else{
PtrS->Data[++(PtrS->Top)]=item;
return;
}
}
PtrS->Data[++(PtrS->Top)]=item;即:
(PtrS->Top)++;
PtrS->Data[PtrS->Top]=item;
- 出栈(返回数组中下标为Top的值,同时Top–)
ElementType Pop(Stack PtrS)
{
if(PtrS->To==-1){
printf("堆栈空");
return ERROR;
}
else
return (PtrS->Data[(PtrS->Top)--]);//先return,再-1,注意单目运算符的位置
}
用一个数组实现两个堆栈
- 要点:使这两个栈分别从数组的两头开始向中间生长,当两个栈的栈顶指针相遇时,表示两个栈都满了
- 实现:
#define MaxSize
struct DStack{
ElementType Data[MaxSize];
int Top1;/*堆栈1的栈顶指针*/
int Top2;/*堆栈2的栈顶指针*/
}S;
S.Top1=-1;
S.Top2=MaxSize;
/*指针跑到外面时两个堆栈都为空*/
- 入栈(要点:区分堆栈——Tag)
void Push(struct DStack *PtrS, ElementType item, int Tag)
{
if(PtrS->Top2-PtrS->Top1==1){/*栈堆满*/
printf("栈堆满");
return;
}
else if(Tag==1)/*对第一个堆栈操作*/
PtrS->Data[++(PtrS->Top1)]=item;
else/*对第二个堆栈操作*/
PtrS->Data[--(PtrS->Top2)]=item;
}
- 出栈
ElementType Pop(struct DStack *PtrS, int Tag)
{
if(Tag==1){/*对第一个堆栈操作*/
if(PtrS->Top1==-1){
printf("堆栈1空");
return NULL;
}
else return PtrS->Data[(PtrS->Top1)--];
}
else{
if(PtrS->Top2==MaxSize){
printf("堆栈2空");
return NULL;
}
else return PtrS->Data[(PtrS->Top2)++];
}
}
2.堆栈的链式存储实现
- 栈的链式存储结构实际上是一个单链表,叫做链栈。
- 插入和删除只能在链栈的栈顶进行
- 栈顶指针Top指向链表的头更加方便
typedef struct SNode *Stack;
struct SNode{
ElementType Data;
struct SNode*Next;
}
(1)堆栈初始化(建一个空栈);
(2)判断堆栈S是否为空
Stack CreatStack()
{/*构建一个堆栈的头结点,返回指针*/
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)
{
Stack TmpCell;
TmpCell=(struct SNode*)malloc(sizeof(struct SNode));
TmpCell->Element=item;
TmpCell->Next=S->Next;
S->Next=TmpCell;
}
- 出栈
ElementType Pop(Stack S)
{/*删除并返回堆栈的栈顶元素*/
Stack FirstCell;
ElementType TopElem;
if(IsEmpty(S)){
printf("堆栈空");return NULL;
}
else{
FirstCell=S->Next;
S->Next= FirstCell->Next;
TopElem=FirstCell->Element;
free(FirstCell);
return TopElem;
}
}
实际上
这里的S是一个哨兵结点,真正的栈顶是S->Next