数据结构(严蔚敏版)第三章——栈和队列(二)【栈的表示和操作的实现】

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指示真正的栈顶元素之上的下标地址

image-20221013084655325

顺序栈的定义:
#define MAXSIZE 100 			// 顺序栈存储空间的初始分配量
typedef struct 
{
  SElemType *base;				// 栈底指针
  SElemType *top;					// 栈顶指针
  int stacksize;					// 栈可用的最大容量
}SqStack;

说明:

  1. base为栈底指针,初始化完成之后,栈底指针始终指向栈底的位置,若base为NULL。则表明栈的结构不存在。top为栈顶指针,其初值指向栈底。每插入新的栈顶元素时,指针top增1;删除栈顶元素时,指针top减1.因此栈空时top和base的值相等,即空栈:base == top;栈非空时,top始终指向栈顶元素的上一个位置。栈满的标志:top - base == stacksize
  2. stacksize指示栈可使用的最大容量,后面的算法将stacksize置为MAXSIZE
  3. 上溢:栈已经满,又要压入元素
  4. 下溢:栈已经空,还要弹出元素
顺序栈的表示:

image-20221013100723572

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、链栈的表示和实现

  • 链栈是运算受限的单链表,只能在链表头部进行操作
  • 链栈的指针指向的元素是数据域的前驱
  • 链表的头指针就是栈顶、不需要头结点,基本不存在栈满的情况
  • 空栈相当于头指针指向空
  • 插入和删除仅在栈顶处执行

image-20221013110241170

链栈的定义:
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;						// 返回栈顶元素的值,栈顶指针不变
  }
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

java小豪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值