栈
栈的基本概念
栈(stack)是只允许在一端进行插入或者删除操作的线性表
重要术语:
栈顶:允许插入和删除的一端
栈底:不允许插入和删除的一端
空栈
特点:“后进先出” LIFO(Last in First out)
创消:
InitStack(&S): 初始化栈。构造一个空栈,分配内存空间
DestroyStack(&S):销毁栈。销毁并释放S所占的内存空间
增删:
Push(&S,x):进栈。若栈S未满,则将x加入使之成为新的栈顶
Pop(&S,&x):出栈。若栈S非空,则弹出栈顶元素,并用x返回。删除栈顶元素
查:栈的使用场景大多只访问栈顶元素
GetTop(&S,&x):读栈顶元素。若栈S非空,并用x返回栈顶元素。不删除栈顶元素
其他常用操作:
StackEmpty(S):判断一个栈S是否为空。若为空,则返回true,否则返回false
栈的顺序存储实现
顺序栈的定义
Sq:sequence —— 顺序
#define MaxSize 10 //定义栈中的元素的最大个数
typrdef struct{
ElemType data[MaxSize]; //静态数组存放栈中元素
int top; //栈顶指针,这里其实是数组下标,没有真的用指针实现
}SqStack;
//初始化栈
void InitStack(SqStack &s){
S.top = -1; //初始化栈顶指针
}
void testStack() {
SqStack S; //声明一个顺序栈(分配空间)
InitStack(s);
//......
}
//判断为空
bool StackEmpty(SqStack){
if (S.top == -1)
return true;
else
return false;
}
进栈操作
- 未满?
- 指针先加1
- 新元素再入栈
//这两句也可以这么写***//
S.data[++S.top] = x;
//注意这里顺序不能返,要++再前,先加1,再使用top
#define MaxSize 10
typedef struct{
ElemType data[MaxSize];
int top;
}SqStack;
//新元素入栈
bool Push(SqStack &S,ElemType x){
if (S.top == MaxSize - 1) //栈满,报错
return false;
S.top += 1; //指针先加1
S.data[S.top] = x; //新元素再入栈
//******这两句也可以这么写*********//
// S.data[++S.top] = x;
//注意这里顺序不能返,要++再前,先加1,再使用top
return true;
}
出栈操作
#define MaxSize 10
typedef struct{
ElemType data[MaxSize];
int top;
}SqStack;
//新元素入栈
bool Pop(SqStack &S,ElemType &x){
if (S.top == - 1) //栈空,报错
return false;
x = S.data[S.top--]//先使用top,再令top-1
//先出栈,栈顶指针再减1
//只是在逻辑上删除,并未在物理上删除
return true;
}
读栈顶元素
bool GetTop(SqStack S,ELEMtYPE &x){
if (S.top == - 1) //栈空,报错
return false;
x = S.data[S.top]; //不删除元素
return true;
}
共享栈
顺序栈的缺点:栈的大小不可变
解决方案:
1.使用链式存储
2. 共享栈的方式:两个栈共享同一片内存空间
共享栈栈满的条件: top1 + 1 == top2
定义共享栈
#define MaxSize 10
typedeef struct{
ElemType data[MaxSize];
int top1;
int top2;
}ShStack;
//初始化栈
void InitStack(ShStack &S){
S.top1 = -1; //初始化栈顶指针
S.top2 = MaxSize;
}
进栈
bool Push(ShStack &S,ElemType e, int stackNumber){
if (S.top1 + 1 == S.top2) //判断栈满的条件
return false;
if (stackNumber == 1)
S.data[++S.top1] = e;
else if (stackNumber == 2)
S.data[--S.top2] = e;
return true;
}
出栈
`bool Pop(ShStack &S,ElemType &e, int stackNumber){
if (stackNumber == 1){
if (S.top1 == -1) //栈1为空
return false;
e = S.data[S.top1--];//将栈顶1元素出栈
}
else if (stackNumber == 2){
if (S.top2 == MaxSize) //栈2为空
return false;
e = S.data[S.top2++];//将栈顶2元素出栈
}
return true;
}
总结
栈的链式存储实现
链栈在本质上是一个只能在单链表的表头进行插入和删除的有限制的单链表。
初始化
typedef int ElemType;
typedef struct SNode {
ElemType data;
struct SNode* next;
}SNode,*LinkStack;
bool InitStzck(LinkStack& S) {
S = NULL; //就是不带头结点的单链表的初始化
return true;
}
入栈
//将新结点压入栈顶,将新结合点插入到第一个结点前面,然后修改栈顶指针
bool Push(LinkStack& S, ElemType e) { //对于链栈来说,基本不存在栈满的情况
SNode *p;
p = (SNode *)malloc(sizeof(SNode)); //生成新结点
p->data = e;
p->next = S; //将新结点插入到第一个结点的前面
S = p; //移动栈顶指针指向前一个的结点
return true;
}
出栈
ElemType Pop(LinkStack& S) {
if (S == NULL) //检查栈是否为空
return -1;
ElemType e;
SNode* p;
p = S;
e = S->data; //数据出栈
S = S->next; //栈顶指针指向后面一个结点
free(p);
return e;
}
取栈顶元素
ElemType GetTop(LinkStack S) {
if (S != NULL)
return S->data;
else
return -1;
}
栈调试函数
void StackShow(LinkStack S) {
if (S == NULL)
cout << "空栈" << endl;
SNode* p = S;
cout << "→";
while (p != NULL) {
cout << "\t" << p->data << endl;
p = p->next;
}
}