数据结构(严蔚敏版)第三章——栈和队列(二)【栈的表示和操作的实现】
3.3、栈的表示和操作的实现
3.3.1、栈的类型定义
栈的基本操作的抽象数据类型定义:
ADT Stack {
数据对象; D = {ai | ai 属于 ElementSet, i = 1, 2, ... , n, n >= 0}
数据关系: R1 = {<ai - 1, ai> | ai - 1, ai 属于 D, i = 2, ... , n }
约定an端为栈顶,a1端为栈底
基本操作:
InitStack(&S)
操作结果:构造一个空栈
DestroyStack(&S)
初始条件:栈S已存在
操作结果:栈S被销毁
ClearStack(&S)
初始条件:栈S已存在
操作结果:将栈S清空为空栈
StackEmpty(S)
初始条件:栈S已存在
操作结果:若栈S为空栈,则返回true,否则则返回false
StackLength(S)
初始条件:栈S已存在
操作结果:返回S的元素个数,即栈的长度
GetTop(S, e)
初始条件:栈S已存在
操作结果:返回S的栈顶元素,不修改栈顶的指针
Push(&S, e)
初始条件:栈S已存在
操作结果:插入元素e为新的栈顶元素
Pop(S)
初始条件:栈S已存在
操作结果:删除S的栈顶元素,并用e返回其值
StackTraverse(S)
初始条件:栈S已存在且非空
操作结果:从栈底到栈顶依次对S的每个数据元素进行访问
}ADT Stack
3.3.2、顺序栈的表示和实现
-
栈的存储方式有两种:顺序存储和链式存储
- 栈的顺序存储——顺序栈
- 栈的链式存储——链栈
-
存储方式:同一般的线性表的顺序存储结构完全相同,
-
利用一组地址连续的存储单元依次存放自栈底到栈顶的数据元素。栈底一般在低地址端
- 附设top,指示栈顶元素在顺序栈中的位置
- 另设base指针,指示栈底元素在顺序栈中的位置
为了方便操作,通常top指示真正的栈顶元素之上的下标地址
顺序栈的定义:
#define MAXSIZE 100 // 顺序栈存储空间的初始分配量
typedef struct
{
SElemType *base; // 栈底指针
SElemType *top; // 栈顶指针
int stacksize; // 栈可用的最大容量
}SqStack;
说明:
- base为栈底指针,初始化完成之后,栈底指针始终指向栈底的位置,若base为NULL。则表明栈的结构不存在。top为栈顶指针,其初值指向栈底。每插入新的栈顶元素时,指针top增1;删除栈顶元素时,指针top减1.因此栈空时top和base的值相等,即空栈:base == top;栈非空时,top始终指向栈顶元素的上一个位置。栈满的标志:top - base == stacksize
- stacksize指示栈可使用的最大容量,后面的算法将stacksize置为MAXSIZE
- 上溢:栈已经满,又要压入元素
- 下溢:栈已经空,还要弹出元素
顺序栈的表示:
1、顺序栈的初始化
【算法步骤】
- 为顺序栈动态分配一个最大容量为MAXSIZE的数组空间,使base指向这段空间的基地址,即栈底
- 栈顶指针top初始为base,表示栈为空
- stacksize置为栈的最大容量MAXSIZE
【算法描述】
Status InitStack(SqStack &S)
{ // 构造一个空栈
S.base = new SElemType[MASIZE]; // 或S.base = (SElemType*)malloc(MAXSIZE*sizeof(SElemType));
if (!S.base) exit (OVERFLOW); // 存储分配失败
S.top = S.base; // 栈顶指针等于栈底指针
S.stacksize = MAXSIZE; // stacksize置为栈的最大容量MAXSIZE
return OK;
}
2、判断顺序栈是否为空
判断条件:是否满足top == base
Status StackEmpty(SqStack S)
{ // 若栈为空,返回TRUE;否则返回FALSE
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 OK;
}
5、销毁顺序栈
Status DestroyStack(SqStack &S)
{
if (S.base)
{
delete S.base;
S.stacksize = 0;
S.base = S.top =NULL;
}
return OK;
}
6、顺序栈的入栈
- 判断栈是否满,若满则返回ERROR
- 将新元素压入栈顶,栈顶指针加1
Status Push(SqStack &S, SElemType e)
{ // 插入元素e为新的栈顶元素
if (S.top - S.base == S.stacksize) return ERROR; // 栈满
*S.top++ = e;
// 或 *S.top = e; S.top++;
return OK;
}
7、顺序栈的出栈
【算法步骤】
- 判断栈是否为空,若为空则返回ERROR
- 栈顶指针减1,栈顶元素出栈
【算法描述】
Status Pop(SqStack &S, SElemType &e)
{ // 删除S的栈顶元素,用e返回其值
if (S.top == S.base) return ERROR; // 栈空
e = *--S.top; // 栈顶指针减1,将栈顶元素赋给e
// 或 e = S.top; S.top--;
return OK;
}
8、取栈顶元素
- 当栈非空时,此操作返回当前栈顶的元素值,栈顶指针保持不变。
【算法描述】
SElemType GetTop(SqStack S)
{ // 返回S的栈顶元素,不修改栈顶指针
if(S.top != S.base) // 栈非空
return *(S.top - 1); // 返回栈顶元素的值,栈顶指针不变
}
3.3.3、链栈的表示和实现
- 链栈是运算受限的单链表,只能在链表头部进行操作
- 链栈的指针指向的元素是数据域的前驱
- 链表的头指针就是栈顶、不需要头结点,基本不存在栈满的情况
- 空栈相当于头指针指向空
- 插入和删除仅在栈顶处执行
链栈的定义:
typedef struct StackNode
{
SElemType data;
struct StackNode *next;
}StackNode, *LinkStack;
LinkStack S;
1、链栈的初始化
void InitStack(LinkStack &S)
{ // 构造一个空栈,栈顶指针置为空
S = NULL;
return OK;
}
2、判断链栈是否为空
Status StackEmpty(LinkStack S)
{
if (S == NULL) return NULL;
elese return FALSE;
}
3、链栈的入栈
【算法步骤】
- 为入栈元素e分配空间,用指针p指向
- 将新结点数据域置为e
- 将新结点插入栈顶
- 修改栈顶指针为p
【算法描述】
Status Push(LinkList &S, SElemType e)
{ // 在栈顶插入元素e
p = new StackNode; // 生成新的结点
p -> data = e; // 将新结点的数据域置为e
p -> next = S; // 将新结点插入栈顶
S = p; // 修改栈顶指针为p
return OK;
}
4、链栈的出栈
【算法步骤】
- 判断栈是否为空,若为空则返回ERROR
- 将栈顶元素赋给e
- 临时保存栈顶指针,指向新的栈顶元素
- 释放原栈顶元素的空间
【算法描述】
Status Pop(LinkStack &S, SElemType &e)
{ // 删除S的栈顶元素,用e返回其值
if (S == NULL)
return ERROR; // 栈空
e = S -> data; // 将栈顶元素赋给e
p = S; // 用p临时保存栈顶元素空间,以备释放
S = S -> next; // 修改栈顶指针
delete p; // 释放原栈顶元素的空间
return OK;
}
5、取栈顶元素
与顺序栈一样,当栈非空时,此操作返回当前栈顶元素的值,栈顶指针S保持不变。
【算法描述】
SElemType GetTop(LinkList S)
{ // 返回S的栈顶元素,不修改栈顶元素
if (S != NULL) // 栈非空
{
return S -> data; // 返回栈顶元素的值,栈顶指针不变
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· DeepSeek在M芯片Mac上本地化部署