前言
提示:以下是本篇文章正文内容
一、栈的定义
栈(Stack)是受操作限制的线性表,插入和删除数据元素的操作只能在线性表的一段进行。
栈一般有栈底和栈顶,stack是限定仅在表尾进行插入和删除操作的线性表,允许插入和删除的一端称为栈顶,另一端称为栈底
栈又称为后进先出的线性表,简称LIFO结构
栈的插入操作,为压栈、入栈;栈的删除操作,为出栈
入栈(Push)
数据元素进入栈内
出栈(Pop)
栈内元素从栈顶弹出
二、顺序栈
顺序栈:栈的顺序存储结构
顺序栈是用数组来实现的,并将下标位0的作为栈底
附设指针top指示栈顶元素在数组中的位置
顺序栈的结构
typedef int SElemType;//SElemType类型根据实际情况来定
/* 顺序栈结构 */
typedef struct
{
SElemType data[MAXSIZE];
int top; //用于栈顶指针
}SqStack;
进栈操作
/*进栈操作 插入元素e为新的栈顶元素*/
Status Push(SqStack *S,SElemType e)
{
if(S->top == MAXSIZE -1) /*栈满*/
{
return ERROR;
}
S->top++; /*栈顶指针增加一*/
S->data[S->top] = e; /*将新插入元素赋值给栈顶空间*/
return OK;
}
出栈操作
/*出栈操作:若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR*/
Status Pop(SqStack *S,SElemType *e)
{
if(S->top == -1)
return ERROR;
*e=S->data[S->top]; /*将要删除的栈顶元素赋值给e*/
S->top--; /*栈顶指针减一*/
return OK;
}
三、两栈共享空间
对于相同数据类型的栈,可以用一个数组来存储,让一个栈的栈底为数组的始端,即下标为0处,另一个栈的栈底为数组的末端,即下标为数组长度n-1处。两个栈如果增加元素,就是两端点向中间延伸。
top1和top2分别为两个栈的栈顶指针
top1+1=top2(栈满);栈1为空栈,top1=-1;栈2为空栈,top2=n;
共享栈结构
/*两栈共享空间结构*/
typedef struct
{
SElemType data[MAXSIZE];
int top1; /*栈1栈顶指针*/
int top2; /*栈2栈顶指针*/
}SqDoubleStack;
入栈操作
这里要判断是栈1还是栈2的栈号参数stacklNumber
//插入元素e为新的栈顶元素
Status Push(SqDoubleStack *S,SElemType e, int stacklNumber)
{
if(S->top1+1==S->top2) /*栈满*/
return ERROR;
if(stacklNumber==1) /*若栈1有元素进栈*/
S->data[++S->top1] = e; /*若栈1给top1+1后给数组元素赋值*/
else if (stacklNumber ==2)/*若栈2有元素进栈*/
S->data[--S->top2]=e; /*若栈2给top2-1后给数组元素赋值*/
return OK;
}
出栈操作
/*若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR*/
Status Pop(SqDoubleStack *S,SElemType *e, int stackNumber)
{
if (stackNumber == 1)
{
if (S->top1 == -1) /*空栈,溢出*/
return ERROR;
*e = S->data[S->top1--]; /*栈1的栈顶元素出栈*/
}
if (stackNumber == 2)
{
if(S->top2==MAXSIZE) /*空栈,溢出*/
return ERROR;
*e = S->data[S->top2++]; /*栈2的栈顶元素出栈*/
}
}
四、链栈
链栈:栈的链接存储结构
将单链表的头部作为栈顶,链栈不需要附设头节点
链栈的结构
//结点
typedef struct StackNode
{
ElemType data;
struct StackNode *next;
}StackNode, *LinkStackPtr;
typedef struct LinkStack
{
LinkStackPtr top; //栈顶指针
int count
}LinkStack;
进栈操作
//进栈操作:单链表有头指针,而栈顶指针也是必须的,因此把栈顶放在单链表的头部
//(头结点->栈顶):相当于头插法;插入新元素e为新的栈顶元素
Status Push(LinkStack *S,SElemType e)
{
LinkStackPtr s=(LinkStackPtr) malloc(sizeof(StackNode)); /*声明新结点*/
s->data = e;
s->next = S->top; /*把当前的栈顶元素赋值给新结点的直接后继*/
S->top = s; /*将新的结点s赋值给栈顶指针*/
S->count++;
return OK;
}
出栈操作
/*出栈操作:用p存储被删除的栈顶结点,将栈顶指针下移一位,最后释放p*/
#include <stdbool.h>
bool StackEmpty(LinkStack S)
{
if(S.top ==NULL) /*如果是空栈,则top为*/
return TRUE;
}
Status Pop(LinkStack *S,SElemType *e)
{
LinkStackPtr p;
if (StackEmpty(*S))
return ERROR;
*e = S->top->data;
p = S->top;
S->top = S->top->next;
free(p);
S->count--;
return OK;
}
总结
提示:这里对文章进行总结:
如果栈的使用过程中元素变化不可预料,有时小,有时大,建议用链栈,反之,如果它的变化在可控范围内,建议用顺序栈。