3.1.1 栈的定义
栈(stack)是限定仅在表尾进行插入和删除操作的线性表;又称为后进先出(Last In First Out)的线性表,简称LIFO结构。
栈的表尾(即an端)称为栈顶(TOP),表头(即a1端)成为栈底;栈的插入操作称为进栈,也称为压栈、入栈,栈的删除操作称为出栈。
栈的结构示意图:

3.1.2 栈的抽象数据类型
ADT Stack{
数据对象:
D = {ai | ai ∈ Elemset, i = 1, 2, ..., n, n >= 0}
数据关系:
R1 = {<ai-1, ai> | ai-1, ai ∈ D, i = 2, ..., n}
约定an端为栈顶,a1端为栈底。
基本操作:
InitStack(*S) //初始化栈
操作结果:构建一个空栈S。
DestoryStack(*S) //销毁栈
初始条件:栈S已存在。
操作结果:栈S被销毁。
StackEmpty(S) //判断S是否为空栈
操作结果:若栈S为空栈,返回TRUE,否则返回FALSE。
StackLength(S) //求栈的长度
初始条件:栈S已存在。
操作结果:返回栈S的元素个数。
GetTop(S, *e) //取栈顶元素
初始条件:栈S已存在且非空。
操作结果:用e返回S的栈顶元素。
ClearStack(*S) //清空栈S
初始条件:栈S已存在。
操作结果:将栈S清空。
PushStack(*S, e) //入栈操作
初始条件:栈S已存在。
操作结果:插入元素e为新的栈顶元素。
PopStack(*S, *e) //出栈操作
初始条件:栈S已存在。
操作结果:删除S的栈顶元素an,并用e返回它的值。
}
3.1.3 栈的顺序表示
存储方式:利用一组地址连续的存储单元一次存放自栈底到栈顶的数据元素,栈底一般在低地址端。
1、附设top指针,指示栈顶元素在顺序栈中的位置。
2、另设base指针,指示栈底元素在顺序栈中的位置。
3、为了方便操作,通常top指针知识真正栈顶元素之上的下标地址。
4、另外使用stacksize表示栈可使用的最大容量。


空栈:base == top是栈空标志
栈满:top - base == stacksize
使用数组作为顺序栈存储方式的特点:简单、方便、但产生溢出(数组大小固定)。
上溢(overflow):栈已经满,又要压入元素。
下溢(underflow):栈已经空,还要弹出元素。
3.1.4 顺序栈的实现
1、方式一:
(1)栈的数据类型定义:
#define MAXSIZE 100
#define TRUE 0
#define FALSE -1
typedef int Status;
typedef int ElemType;
typdef struct
{
ElemType *base; //栈顶指针
ElemType *top; //栈底指针
int stacksize; //栈的最大容量
}SqStack;
(2)判断栈是否为空
//判断栈是否为空,只需判断top指针和base指针的指向是否相等
Status StackEmpty(SqStack S)
{
if (S.top == S.base)
return TRUE;
else
return FALSE;
}
(3)求栈的长度
int StackLength(SqStack S)
{
//两个指针相减求长度只适用于两个指针都指向同一个数组
return S.top - S.base;
}
(4)清空栈
Status ClearStack(SqStack *S)
{
if (S.base) //判断栈是否存在
S.top = S.base;
return TRUE;
}
(5)销毁栈
Status DestoryStack(SqStack *S)
{
ElemType *p;
if (S->base)
{
for (int i = 0; i < S->stacksize; i++)
{
p = S->base;
S->base++;
free(p);
p = NULL;
}
S->stacksize = 0;
S->base = S->top = NULL;
}
return TRUE;
}
(6)入栈操作
Status PushStack(SqStack *S, ElemType e)
{
if (S->top - S->base == S->stacksize) //判断栈是否已满
return FALSE;
*(S->top) = e;
S->top++;
return TRUE;
}
(7)出栈操作
Status PopStack(SqStack *S, ElemType *e)
{
if (S->base == S->top) //判断栈是否为空
return FALSE;
S->top--;
e = S->top;
return TRUE;
}
2、方式二
(1)栈的数据类型定义
#define MAXSIZE 100
#define TRUE 0
#define FLASE -1
typedef int ElemType;
typedef int Status;
typedef struct
{
ElemType data[MAXSIZE];
int top; //用于保存栈顶元素的下标
}SqStack;
(2)判断栈是否为空
Status StackEmpty(SqStack S)
{
if (S.top == 0)
return TRUE;
else
return FALSE;
}
(3)求栈的长度
int StackLength(SqStack)
{
return S.top;
}
(4)清空栈
Status ClearStack(SqStack *S)
{
S.top = 0;
return TRUE;
}
(5)入栈操作
Status PushStack(SqStack *S, ElemType e)
{
if (S->top == MAXSIZE)
return FALSE;
S->data[S->top] = e;
S->top++;
return TRUE;
}
(6)出栈操作
Status PopStack(SqStack *S, ElemType *e)
{
if (S->top == 0)
return FALSE;
S->top--;
*e = S->data[S->top];
return TRUE;
}
3.1.5 栈的链式存储结构
3.1.5.1 链栈的表示
链栈是运算受限的单链表,只能在链表头部进行操作。

(1)链栈的头指针就是栈顶
(2)不需要头结点
(3)基本不存在栈满的情况
(4)空栈相当于头指针指向空
(5)插入和删除均在栈顶操作
3.1.5.2 链栈的实现
1、链栈的类型定义
typedef struct StackNode
{
ElemType data;
StackNode *next;
}StackNode, *LinkStackPtr;
typedef struct LinkStack
{
LinkStackPtr top;
int count;
}LinkStack;
2、链栈的初始化
Status InitLinkStack(LinkStack *S)
{
S->LinkStackPtr = NULL;
S->count = 0;
return TRUE;
}
3、取栈的长度
int LinkStackLength(LinkStack S)
{
return S.count;
}
4、链栈的入栈操作
Status PusLinkStack(LinkStack *S, ElemType e)
{
LinkStackPtr p = (LinkStackPtr)malloc(sizeof(StackNode));
p->data = e;
p->next = S->top;
S->top = p;
S->count++;
return TRUE;
}
5、链栈的出栈操作
Status PopLinkStack(LinkStack *S, ElemType *e)
{
if (S->count == 0)
return FALSE;
LinkStackPtr p;
*e = S->top->data;
p = S->top;
S->top = S->top->next;
S->count--;
free(p);
p = NULL;
return TRUE;
}
本文详细介绍了栈的定义、抽象数据类型、顺序存储结构及其操作实现,包括栈的初始化、判断空栈、获取栈长度、清空栈、销毁栈、入栈和出栈。此外,还提到了栈的链式存储结构及其操作,如链栈的初始化、入栈和出栈。内容涵盖了栈的基本概念和常用操作,适合计算机科学初学者理解。
2万+

被折叠的 条评论
为什么被折叠?



