堆栈
后缀表达式
中缀表达式:运算符在操作数中间,如a+bc-d/e
后缀表达式:运算符在操作数之后,如abc+de/-
堆栈的抽象数据类型描述
堆栈(Stack):具有一定操作约束的线性表
只在一端做插入删除
插入数据:进栈
删除数据:出栈
后入先出:Last In First Out(LIFO)
数据对象集:一个有0个或多个元素的有穷线性表
操作集:长度为MaxSize的堆栈S∈Stack,堆栈元素item∈ElementType
Stack CreateStack(int MaxSize)
生成空堆栈,其最大长度为MaxSize
int IsFull(Stack S,int MaxSize)
判断堆栈是否已满
void Push(Stack S,ElementType item)
将item插入堆栈S
int IsEmpty(Stack S)
判断堆栈S是否为空
ElementType Pop(Stack S)
删除并返回堆栈S的栈顶元素
栈的顺序存储实现
栈的顺序存储结构通常由一个一维数组和一个记录栈顶元素位置的变量组成
# 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;
}
}
出栈
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){//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(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)++];
}
}
栈的链式存储实现
栈的链式存储结构实际上就是一个单链表,叫做链栈,插入和删除操作只能在链栈的栈顶进行
typedef struct SNode *Stack;
struct SNode{
ElementType Data;
struck 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);
}
(3)入栈
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;
}
(4)出栈
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;
}
}
中缀表达式转化后缀表达式
从头到尾读取中缀表达式的每一个对象,对不同对象按不同的情况处理
- 运算数:直接输出
- 左括号:进栈
- 右括号:出栈,将栈顶元素输出直到遇到左括号
- 运算符:
- 若优先级大于栈顶运算符,则直接进栈
- 若优先级小于等于栈顶运算符时,将栈顶运算符弹出并输出,再比较新的栈顶运算符,直到优先级大于栈顶运算符,然后再进栈
- 若个对象处理完毕,则把堆栈中存留的运算符一并输出
中缀转换为后缀示例:(2 * (9 + 6 / 3 - 5) + 4)
待处理 | 栈 | 输出 |
---|---|---|
2 * (9 + 6 / 3 - 5) + 4 | ||
* (9 + 6 / 3 - 5) + 4 | 2 | |
(9 + 6 / 3 - 5) + 4 | * | 2 |
9 + 6 / 3 - 5) + 4 | * ( | 2 |
+ 6 / 3 - 5) + 4 | * ( | 2 9 |
6 / 3 - 5) + 4 | * ( + | 2 9 |
/ 3 - 5) + 4 | * ( + | 2 9 6 |
3 - 5) + 4 | * ( + / | 2 9 6 |
- 5) + 4 | * ( + / | 2 9 6 3 |
5) + 4 | * ( - | 2 9 6 3 / + |
) + 4 | * ( - | 2 9 6 3 / + 5 |
+ 4 | * | 2 9 6 3 / + 5 - |
4 | + | 2 9 6 3 / + 5 - * |
+ | 2 9 6 3 / + 5 - * 4 | |
2 9 6 3 / + 5 - * 4 + |
栈的应用
函数调用及递归实现
深度优先搜索
回溯算法