栈和队列的概念、表示和实现

news2025/1/17 15:29:01

文章目录

  • 前言
  • 一、栈
    • 1.定义和特点
    • 2.栈的抽象类型定义
    • 3.顺序栈的表示
    • 4. 顺序栈基本操作的实现
  • 二、队列
    • 1.定义和特点
    • 2.队列的抽象数据类型定义
    • 3.队列的顺序表示
    • 4.循环顺序队列
    • 5. 循环顺序队列基本操作的实现
  • 总结


前言

  T_T此专栏用于记录数据结构及算法的(痛苦)学习历程,便于日后复习(这种事情不要啊)。所用教材为《数据结构 C语言版 第2版》严蔚敏。


一、栈

1.定义和特点

  栈 (stack) 是限定仅在表尾进行插入或删除操作的线性表。 因此,对栈来说,表尾端有其特殊含义,称为栈顶 (top);相应地,表头端称为栈底(bottom)。不含元素的空表称为空栈。
  假设栈 S = (a1, a2, …,an),则称 a1 为栈底元素,an 为栈顶元素。栈中元素按 a1, a2, ···, an的次序进栈, 退栈的第一个元素应为栈顶元素 an。 换句话说,栈的修改是按后进先出的原则进行的。因此,栈又称为后进先出 (Last In First Out, LIFO) 的线性表, 它的这个特点可用铁路调度站形象地表示。
在这里插入图片描述

2.栈的抽象类型定义

  栈的基本操作除了入栈和出栈外, 还有栈的初始化、 栈空的判定,以及取栈顶元素等。下面给出栈的抽象数据类型定义:

ADT Stack |
数据对象: D={ai | ai ∈ ElemSet, i=1, 2, …,n,n>=0}
数据关系: R= { < ai-1, ai > | ai-1,ai ∈ D, i=2, …,n }
约定 an 端为栈顶, a1端为栈底。
基本操作:
InitStack(&S)
操作结果:构造一个空栈s。
DestroyStack(&S)
初始条件:栈s已存在。
操作结果:栈S被销毁。
ClearStack(&S)
初始条件:栈S已存在。
操作结果:将S清为空栈。
StackEmpty(S)
初始条件:栈S已存在。
操作结果:若栈 s 为空栈,则返回 true, 否则返回 false。
StackLength (S)
初始条件:栈S已存在。
操作结果:返回s的元素个数, 即栈的长度。
GetTop(S)
初始条件:栈S已存在且非空。
操作结果:返回s的栈顶元素, 不修改栈顶指针。
Push(&S,e)
初始条件:栈S已存在。
操作结果:插入元素e为新的栈顶元素。
Pop(&S,&e)
初始条件:栈s已存在且非空。
操作结果:删除S的栈顶元素,并用e返回其值。
StackTraverse(S)
初始条件:栈S已存在且非空。
操作结果:从栈底到栈顶依次对S的每个数据元素进行访问。
}ADT Stack

3.顺序栈的表示

  栈有两种存储表示方法,分别称为顺序栈和链栈,顺序栈更为常见。
  顺序栈是指利用顺序存储结构实现的栈,即利用一组地址连续的存储单元依次存放自栈底到栈顶的数据元素,同时附设指针 top 指示栈顶元素在顺序栈中的位置。通常习惯的做法是:以 top=0 表示空栈,鉴于 C 语言中数组的下标约定从 0 开始,则当以 C 语言作描述语言时,如此设定会带来很大不便,因此另设指针 base 指示栈底元素在顺序栈中的位置。当 top 和 base 的值相等时,表示空栈。
  实际上,top 指向栈下一个元素的存放位置,如栈中已有一个元素存放在位置0,则 top 指向位置1;若最后一个元素位置在n,则 top 指向 n+1。
  顺序栈的定义如下:

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

在这里插入图片描述

4. 顺序栈基本操作的实现

  由于顺序栈的插入和删除只在栈顶进行, 因此顺序栈的基本操作比顺序表要简单得多。顺序表中给出了顺序表基本操作的实现,可据此类推顺序栈基本操作的实现(真不是偷懒555…)。

二、队列

1.定义和特点

  队列(queue)是一种先进先出(First In First Out, FIFO)的线性表。它只允许在表的一端进行插入,而在另一端删除元素。这和日常生活中的排队是一致的,最早进入队列的元素最早离开。在队列中,允许插入的一端称为队尾(rear), 允许删除的一端则称为队头(front)。假设队列为q =(a1, a2, …,an), 那么,a1就是队头元素,an则是队尾元素。队列中的元素是按照 a1,a2,…,an的顺序进入的,退出队列也只能按照这个次序依次退出,也就是说只有在a1, a2…an-1 都退出队列后,an才能退出队列。
在这里插入图片描述

2.队列的抽象数据类型定义

  队列的操作与栈的操作类似,不同的是,队列删除是在表的头部(即队头)进行。下面给出队列的抽象数据类型定义:

ADT Queue (
数据对象:D={ai |ai ∈ ElemSet ,i=l,2,…,n ,n>=0}
数据关系:R={ <ai-1,ai> | ai-1,ai ∈ D , i=2, …,n}
约定其中a1端为队列头,an端为队列尾。
基本操作:
InitQueue(&Q)
操作结果:构造一个空队列Q。
DestroyQueue(&Q)
初始条件:队列Q已存在。
操作结果:队列Q被销毁,不再存在。
ClearQueue(&Q)
初始条件:队列Q巳存在。
操作结果:将Q清为空队列。
QueueEmpty(Q)
初始条件:队列Q已存在。
操作结果:若Q为空队列,则返回true, 否则返回false。
QueueLength(Q)
初始条件:队列Q已存在。
操作结果:返回Q的元素个数,即队列的长度。
GetHead(Q)
初始条件:Q为非空队列。
操作结果:返回Q的队头元素。
EnQueue(&Q, e)
初始条件:队列Q已存在。
操作结果:插入元素e为Q的新的队尾元素。
DeQueue(&Q, &e)
初始条件:Q为非空队列。
操作结果:删除Q的队头元素,并用e 返回其值。
QueueTraverse(Q)
初始条件:Q巳存在且非空。
操作结果:从队头到队尾,依次对Q的每个数据元素访问。
) ADT Queue

3.队列的顺序表示

  队列具有两种存储表示,顺序表示和链式表示。
  和顺序栈相类似,在队列的顺序存储结构中,除了用一组地址连续的存储单元依次存放从队列头到队列尾的元素之外,尚需附设两个整型变量 front 和 rear分别指示队列头元素及队列尾元素的位置(后面分别称为头指针和尾指针)。
  为了在 C 语言中描述方便起见,约定:初始化创建空队列时,令 front = rear = 0 , 每当插入新的队列尾元素时,尾指针 rear增1; 每当删除队列头元素时, 头指针 front增1。因此,在非空队列中,头指针始终指向队列头元素,而尾指针始终指向队列尾元素的下一个位置。
在这里插入图片描述

  队列的顺序存储结构表示如下:

//----- 队列的顺序存储结构-----
#define MAXQSIZE 100  //队列可能达到的最大长度
typedef struct 
{ 
QElemType *base;   //存储空间的基地址
int front;         //头指针
int rear; 		   //尾指针
) SqQueue;

4.循环顺序队列

  假设当前队列分配的最大空间为 6, 则当队列处于下图所示的状态时不可再继续插入新的队尾元素,否则会出现溢出现象, 即因数组越界而导致程序的非法操作错误。 事实上,此时队列的实际可用空间并未占满,所以这种现象称为“假溢出"。这是由 "队尾入队,队头出队” 这种受限制的操作造成的。
在这里插入图片描述
  循环队列可以很好地解决这个问题。
  将顺序队列变为一个环状的空间,头、 尾指针以及队列元素之间的关系不变 ,只是在循环队列中,头、 尾指针"依环状增1"的操作可用"模"运算来实现。 通过取模,头指针和尾指针就可以在顺序表空间内以头尾衔接的方式"循环"移动。
在这里插入图片描述
  在下图(a)中,队头元素是 J5, 在元素J6入队之前,在 Q.rear 的值为 5,当元素J6入队之后,通过"模"运算,Q.rear = (Q.rear + 1)%6, 得到 Q.rear 的值为 0, 而不会出现"假溢出"状态。
  在下图(b)中,J7、J8、J9、J10相继入队,则队列空间均被占满,此时头、尾指针相同。
  在下图(c)中, 若 J5 和 J6 相继从 (a) 所示的队列中出队, 使队列此时呈 "空"的状态,头、尾指针的值也是相同的。

在这里插入图片描述
  由此,循环队列不能以头、尾指针的值是否相同来判别队列空间是"满"还是"空"。
  为了判断循环队列的状态,有两种处理方法:
  1.少用一个元素空间, 即队列空间大小为m时,有m-1个元素就认为是队满。
  2.另设一个标志位以区别队列是"空"还是"满"。

5. 循环顺序队列基本操作的实现

  由于循环顺序队列的插入和删除分别在队列的两端进行, 因此循环顺序队列的基本操作比顺序表要简单得多。顺序表中给出了顺序表基本操作的实现,可据此类推循环顺序队列基本操作的实现(真不是偷懒555…)。


总结

  路漫漫其修远兮,吾将上下而摆烂。
  有任何疑问和补充,欢迎交流。(但我显然不会)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1622869.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CSS常用属性之(列表、表格、鼠标)属性,(如果想知道CSS的列表、表格、鼠标相关的属性知识点,那么只看这一篇就足够了!)

前言&#xff1a;在学习CSS的时候&#xff0c;必不可少的就要学习选择器和常见的属性&#xff0c;而本篇文章讲解的是CSS中的列表、表格、背景、鼠标属性。 ✨✨✨这里是秋刀鱼不做梦的BLOG ✨✨✨想要了解更多内容可以访问我的主页秋刀鱼不做梦-CSDN博客 大致了解一下本篇文章…

协议的定制之序列化与反序列化 | 守护进程

目录 一、再谈协议 二、序列化与反序列化 三、网络计算器的简单实现 四、网络计算器完整代码 五、代码改进 六、守护进程 七、Json序列化与反序列化 八、netstat 一、再谈协议 是对数据格式和计算机之间交换数据时必须遵守的规则的正式描述。简单的说了&#xff0c;网络…

SpringCloud 之 服务消费者

前提 便于理解请我修改了本地域名》这里!!! 127.0.0.1 eureka7001.com 127.0.0.1 eureka7002.com 127.0.0.1 eureka7003.comRest学习实例之消费者 创建一个消费者去消费 消费者模块展示 1、导入依赖 <!-- 实体类api自己创建的模块 Web 部分依赖展示--><de…

jmeter之跨线程关联

1&#xff09;_setproperty函数&#xff1a;将值保存成jmeter属性 2&#xff09;_property函数&#xff1a;在其他线程组中使用property函数读取属性 一、跨线程接口引用变量 1. 法一&#xff1a;jmeter自带函数_setProperty和_property 1. 1线程组 01 创建登录的【HTTP请求】…

OriginPro作图之箱线图

前言 箱线图(Box-plot) 又称为盒须图、盒式图或箱线图&#xff0c;是一种用作显示一组数据分散情况资料的统计图。因型状如箱子而得名。 本文将结合实例阐述其意义和绘图过程。 箱线图简介 箱线图(Boxplot) 也称箱须图( Box-whisker Plot)&#xff0c;是利用数据中的五个统计量…

FANUC机器人socket通讯硬件配置

一、添加机器人选配包 Fanuc机器人要进行socket通讯&#xff0c;需要有机器人通讯的选配包&#xff0c;1A05B-2600-R648 User Socket Msg&#xff0c;1A05B-2600-R632 KAREL&#xff0c;1A05B-2600-R566 KAREL Diagnostic&#xff0c;1A05B-2600-J971 KAREL Use Sprt FCTN。 二…

有没有一本从电路开始讲然后汇编再到C语言的书?

在开始前我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「C语言的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&#xff01; 没有一本书或者几本书能把这整…

【NPU】A800-9000服务器8*Ascend 910 B的HCCS测试

HCCS集合通信带宽数据 HCCS集合通信带宽数据timeline信息在msprof_*.json文件的HCCS层级展示 summary信息在hccs_*.csv文件汇总。 支持的型号 Atlas 训练系列产品 Atlas A2训练系列产品 测试命令 npu-smi info -t topo结果展示 NPU0 NPU1 NPU2 NPU3 …

微信小程序实现美食检索功能

1、打开浏览器搜索&#xff1a;腾讯位置服务 2、注册一个账号&#xff0c;有账号的直接登陆就行 3、注册登陆成功后&#xff0c;点击控制台 4、进入控制台后点击我的应用——>创建应用 5、添加key,注意看注释 6、key添加成功后&#xff0c;开始分配额度&#xff08;配额&…

人工智能(AI)与地理信息技术(GIS)的融合:开启智能地理信息时代

随着科技的不断发展&#xff0c;人工智能&#xff08;AI&#xff09;和地理信息技术&#xff08;GIS&#xff09;的应用越来越广泛&#xff0c;两者的结合更是为许多行业带来了前所未有的变革。本文将以“人工智能&#xff08;AI&#xff09;地理信息技术&#xff08;GIS&#…

【C++】5.C语言/C++内存管理

一、C/C内存分布 栈中存储的是局部变量&#xff0c;函数参数&#xff0c;返回值等 堆主要用于动态内存分配 数据段用以存储全局数据和静态数据 代码段存储可执行代码和常量 二、C语言和C中的内存管理方式 在C语言中&#xff0c;我们使用 malloc、calloc、realloc、free来进…

理解与使用Linux设备树编译器(DTC)

这里写目录标题 设备树简介设备树编译器&#xff08;DTC&#xff09;安装DTC使用DTC实例&#xff1a;编辑设备树小结参考资料 Linux设备树编译器&#xff08;DTC&#xff09;是一个关键工具&#xff0c;用于处理嵌入式Linux系统中的设备树文件。本文将介绍设备树的概念、DTC的基…

深入理解 Srping IOC

什么是 Spring IOC&#xff1f; IOC 全称&#xff1a;Inversion of Control&#xff0c;翻译为中文就是控制反转&#xff0c;IOC 是一种设计思想&#xff0c;IOC 容器是 Spring 框架的核心&#xff0c;它通过控制和管理对象之间的依赖关系来实现依赖注入&#xff08;Dependenc…

每日一题:托普利茨矩阵

给你一个 m x n 的矩阵 matrix 。如果这个矩阵是托普利茨矩阵&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 如果矩阵上每一条由左上到右下的对角线上的元素都相同&#xff0c;那么这个矩阵是 托普利茨矩阵 。 示例 1&#xff1a; 输入&#xff1a;matrix…

最新windows版本erlang26.0和rabbitmq3.13下载

Erlang下载 官网下载&#xff1a;https://www.erlang.org/patches/otp-26.0 百度网盘&#xff1a;https://pan.baidu.com/s/1xU4syn14Bh7QR-skjm_hOg 提取码&#xff1a;az1t RabbtitMQ下载 官网下载&#xff1a;https://www.rabbitmq.com/docs/install-windows 百度网盘…

【C++题解】1302. 是否适合晨练?

问题&#xff1a;1302. 是否适合晨练&#xff1f; 类型&#xff1a;分支 题目描述&#xff1a; 夏天到了&#xff0c;气温太高&#xff0c;小明的爷爷每天有晨练的习惯&#xff0c;但有时候温度不适合晨练&#xff1b;小明想编写一个程序&#xff0c;帮助爷爷判断温度是否适合…

同一工程中不同RS的问题结论

目录 MeshDevice/deviceAll && /wvp/device ​编辑 故意改成mesh下的RS,结果包裹了&#xff1a; sys2/redishealth ​编辑 ​编辑 原因解析 MeshDevice/deviceAll && /wvp/device 测试结果&#xff1a;都使用 import com.gbcom.wvp.domain.vo.RS; 返…

C语言编程题_3D接雨水

接雨水的题目描述如下。 (1) 2D接雨水&#xff1a; 字节员工是不是个个都会接雨水 &#xff1b; (2) 3D接雨水&#xff1a; 407. 接雨水 II &#xff1b; (3) 3D接雨水&#xff1a; 字节人都会的 3D接雨水 。 问题描述 难度&#xff1a;困难 给你一个 m x n 的矩阵&#xff…

【历史版本火狐浏览器下载】

历史版本火狐浏览器下载 介绍 火狐浏览器是一款开源的互联网浏览器&#xff0c;由Mozilla基金会开发。它的历史版本可以追溯到2002年&#xff0c;以下是一些重要的历史版本介绍&#xff1a; Firefox 1.0&#xff08;2004年&#xff09;- 这是火狐浏览器的第一个正式版本&…

安装多个MySQL版本时如何连接到不同的数据库

当安装多个版本的数据库时&#xff0c;不同版本的端口名不一样&#xff0c;可以使用以下命令进行连接 mysql -uroot -p数据库密码 -h主机名 -P端口号 数据库主机名默认是localhost&#xff0c;端口号默认是3306&#xff0c;当安装多个版本数据库时&#xff0c;需要记住数据库的…