栈
栈的基本概念
栈的定义
只允许在一端进行插入或删除操作的线性表
重要术语:
栈顶(允许被插入和删除的一端)、栈底(不允许被插入和删除的一段)、空栈
特点:
后进先出(LIFO – last in first out)
栈的基本操作
InitStack(&S)
初始化栈
DestroyStack(&L)
销毁栈 销毁并释放栈S所占用的内存空间
Push(&S,x)
进栈 若栈S未满 将x加入使之成为新栈顶
Pop(&S,&x)
出栈 若栈S非空 则弹出栈顶元素 并用x返回
GetTop(S,&x)
读栈顶元素 若栈S非空 并用x返回栈顶元素
StackEmpty(S)
判断栈是否为空 若S为空 则返回true 若不为空 返回false
[!CAUTION]
常考题型
若进栈顺序为a → b → c → d → e ,有哪些合法的出栈顺序?
①全部进栈后出战 e d c b a
②全部元素未完全进栈 便出栈部分元素 eg. b e d c a (共有41种)
n个不同元素进栈 出栈顺序共有 (2n)!/(n+1)n! 种 (卡特兰数)
顺序栈的实现
顺序栈的定义
#define MaxSize 10
typedef struct{
ElemType data[MaxSize]; //静态数组存放栈中元素
int top; //栈顶指针
}SqStack;
void testStack(){
SqStack S; //声明一个顺序栈(分配空间)
//后续操作……
}
初始化操作
#define MaxSize 10
typedef struct{
ElemType data[MaxSize]; //静态数组存放栈中元素
int top; //栈顶指针
}SqStack;
//初始化栈
void InitStack(SqStack &S){
S.top = -1;
}
//判断栈空
bool StackEmpty(SqStack S){
return S.top == -1;
}
void testStack(){
SqStack S; //声明一个顺序栈(分配空间)
//后续操作……
}
进栈操作
bool Push(SqStack &S,ElemType x){
if(S.top == MaxSize) return false; //栈满 报错
S.top += 1; //指针先+1
S.data[S.top] = x; //新元素入栈
return true;
}
指针+1与新元素入栈两句代码也可以直接使用 S.data[++S.top] = x;
代替
[!NOTE]
注意区分
x++
与++x
的区别
x++
:先使用x的值 再使x+1
++x
:先让x+1 再使用x的值(此时x的值是+1之后的值)
出栈操作
bool Pop(SqStack &S,ElemType &x){
if(S.top == -1) return false; //栈空,报错
x = S.data[S.top]; //栈顶元素先出栈
S.top -= 1; //指针-1
return true;
}
栈满的条件 top == MaxSize
栈的缺点:栈的长度不可变
共享栈
两个栈共享一片空间
#define MaxSize 10
typedef struct{
ElemType data[MaxSize];
int top0;
int top1;
}ShStack;
void InitStack(ShStack &S){
S.top0 = -1; //初始化栈顶
S.top1 = MaxSize;
}
栈满的条件 top0 + 1 == top1
链栈
链栈的定义和初始化(带头结点)
typedef struct Linknode{
ElemType data;
struct Linknode *next;
}*LiStack;
//初始化栈
void InitStack(LiStack &S){
S = (Linknode *)malloc(sizeof(Linknode));
if(S == NULL) return false;
S->next = NULL;
return true;
}
//判断栈空
bool StackEmpty(LiStack S){
return S->next == NULL;
}
void testStack(){
LiStack S; //声明一个顺序栈(分配空间)
//初始化一个空栈
InitStack(S);
//后续操作……
}
进栈操作
bool Push(LiStack &S,ElemType x){
Linknode *p = (Linknode *)malloc(sizeof(Linknode));
p->data = x;
p->next = S->next; //将新元素存放到头指针之后
S->next = p;
}
出栈操作
bool Pop(LiStack &S,ElemType &x){
if(S->next == NULL) return false; //栈空,报错
x = S->next->data; //栈顶元素先出栈
Linknode *p = S->next;
S->next = p->next; //将p结点从链中断开
free(p); //释放节点的存储空间
return true;
}