栈是一种只能在一端进行插入和删除操作的线性表。允许进行插入、删除的一端称为栈顶,另一端称为栈底。栈的插入操作通常称为进栈或入栈栈的删除操作叫出栈或退栈。
栈的主要特点是后进先出,即后进栈的元素先出栈。每次进栈的数据元素都放在栈顶元素之前成为新的栈顶元素。每次出栈的元素都是当前栈顶元素。
栈可以像线性表一样采用顺序存储的方式进行存储数据也可以采用链式存储的方式存储数据,采用顺序存储结构的栈称为顺序栈,采用链式存储结构的栈称为链栈。
一、顺序栈
1.对顺序栈操作四个非常重要的要素。
- 栈空的条件:s->top == -1。
- 栈满的条件:s->top == MaxSize -1(数组的最大下标)
- 元素e的进栈操作:先将栈顶指针 top 增1,然后将元素 e 放在栈顶指针处。
- 出栈操作:先将栈顶指针 top 处的元素取出放在 e 中,然后将栈顶指针减1。
顺序栈操作示意图如下:
2.顺序栈的实现:
1.定义顺序栈的类型
#define MaxSize 50
typedef int ElemType;
typedef struct
{
ElemType data[MaxSize]; //存放栈中的数据元素
int top; //栈顶指针,即存放栈顶元素在data数组中的下标
}SqStack; //顺序栈类型
2.初始化栈
void InitStack(SqStack * &s)
{
s = (SqStack*)malloc(sizeof(SqStack)); //分配一个顺序栈空间,首地址存放在s中
s->top == -1; //栈顶指针置为 -1
}
3.销毁栈
void DestoryStack(SqStack * &s)
{
free(s);
}
4.判断栈是否为空
bool StackEmpty(SqStack * s)
{
return (s->top == -1);
}
5.进栈
bool Push(SqStack * &s, ElemType e)
{
if (s->top == MaxSize - 1) //栈满情况
return false;
s->top++; //栈顶指针增1
s->data[s->top] = e; //元素e放在栈顶指针处
return true;
}
6.出栈
bool Pop(SqStack * &s, ElemType &e)
{
if (s->top == -1) //栈为空情况
return false;
e = s->data[s->top]; //取出栈顶元素
s->top--; //栈顶指针减1
return true;
}
7.获取栈顶元素
bool GetTop(SqStack * s, ElemType &e)
{
if (s->top == -1) //栈为空情况
return false;
e = s->data[s->top]; //取出栈顶元素
return true;
}
二、链栈
1.对顺序栈操作四个非常重要的要素。
- 栈空的条件:s->top == NULL。
- 栈满的条件:只有内存溢出时才会出现栈满,通常不考虑。
- 元素e的进栈操作:新建一个结点存放元素e(由p指向它),然后将p插入到头节点之后。
- 出栈操作:取出首结点的data值并将其删除。
顺序栈操作示意图如下:
2.链栈的实现:
1.定义链栈的类型
typedef int ElemType;
typedef struct linknode
{
ElemType data; //数据域
struct linknode * next; //指针域
}LinkStNode; //链栈结点类型
2.初始化栈
void InitStack(LinkStNode * &s)
{
s = (LinkStNode*)malloc(sizeof(LinkStNode));
s->next == NULL;
}
3.销毁栈
void DestoryStack(LinkStNode * &s)
{
LinkStNode *pre = s, *p = s->next; //pre指向头结点,p指向首结点
while (p != NULL) //循环到p为空
{
free(pre); //释放pre结点
pre = p; //p、pre同步后移
p = pre->next;
}
free(pre);
}
4.判断栈是否为空
bool StackEmpty(LinkStNode * s)
{
return (s->next == NULL);
}
5.进栈
void Push(LinkStNode * &s, ElemType e)
{
LinkStNode *p;
p = (LinkStNode*)malloc(sizeof(LinkStNode));
p->data = e; //存放元素e
p->next = s->next; //将p结点插入作为首结点
s->next = p;
}
6.出栈
bool Pop(LinkStNode * &s, ElemType &e)
{
LinkStNode *p;
if (s->next == NULL) //栈为空情况
return false;
p = s->next; //p指向首结点
e = p->data; //提取首结点值
s->next = p->next; //删除首结点
free(p); //释放被删除结点的空间
return true;
}
7.获取栈顶元素
bool Getnext(LinkStNode * s, ElemType &e)
{
if (s->next == -NULL) //栈为空情况
return false;
e = s->next->data; //提取首结点值
return true;
}