栈是限定仅在表尾进行插入和删除操作的线性表。
允许插入和删除的一端称为栈顶,另一端称为栈底,不含任何数据元素的栈称为空栈。
栈又称为后进先出的线性表,简称LIFO结构。
栈的插入操作,叫做进栈,也称压栈,入栈。栈的删除操作,叫做出栈,也称弹栈。
最先进栈的元素是不是只能是最后出栈?答案是不一定!
栈的顺序存储结构
数组下标为0的一端作为栈底,定义top变量来指示栈顶元素在数组中的位置。
空栈:top = -1
栈满:top = MAXSIZE - 1
顺序栈的结构定义:
typedef int SElemType;
typedef struct
{
SElemType data[MAXSIZE];
int top;
} SqStack;
顺序栈的入栈操作:
Status Push(SqStack *S, SElemType e)
{
if (S->top == MAXSIZE - 1)
return ERROR;
S->top++;
S->data[S->top] = e;
return OK;
}
顺序栈的出栈操作:
Status Pop(SqStack *S, SElemType *e)
{
if (S->top == -1)
return ERROR;
*e = S->data[S->top];
S->top--;
return OK;
}
出入栈操作没有涉及到任何循环语句,时间复杂度是
O(1)。
两栈共享空间
数组有两个端点,两个栈有两个栈底,让一个栈的栈底为数组的始端,即下标为0处,另一个栈为数组的末端,即下标为n-1处。两个栈如果增加元素,就是两个端点向中间延伸。
栈1为空:top1 = -1;栈2为空:top2 = n
栈满:top 1+ 1 = top2
两栈共享空间的结构:
typedef struct
{
SElemType data[MAXSIZE];
int top1;
int top2;
} SqDoubleStack;
两栈共享空间的Push操作:
Status Push(SqDoubleStack *S, SElemType e, int stackNumber)
{
if (S->top1 + 1 == S->top2)
return ERROR;
if (stackNumber == 1)
S->data[++S->top1] = e;
else if (stackNumber == 2)
S->data[--S->top2] = e;
return OK;
}
两栈共享空间的Pop操作:
Status Pop(SqDoubleStack *S, SElemType *e, int stackNumber)
{
if (stackNumber == 1)
{
if (S->top1 == -1)
return ERROR;
*e = S->data[S->top1--];
}
else if (stackNumber == 2)
{
if (S->top2 == MAXSIZE)
return ERROR;
*e = S->data[S->top2++];
}
return OK;
}
链式栈
链式栈不需要头结点,只需要一个栈顶指针top。
栈为空:top = NULL
链式栈的结构:
typedef struct StackNode
{
SElemType data;
struct StackNode *next;
} StackNode, *LinkStackPtr;
typedef struct LinkStack
{
LinkStackPtr top;
int count;
} LinkStack;
链式栈的入栈:
Status Push(LinkStack *S, SElemType e)
{
LinkStackPtr s = (LinkStackPtr)malloc(sizeof(StackNode));
s->data = e;
s->next = S->top;
S->top = s;
S->count++;
return OK;
}
链式栈的出栈:
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;
}
出入栈操作没有涉及到任何循环语句,时间复杂度是
O(1)。