数据结构严蔚敏--第三章--栈和队列
第三章--栈和队列
- 前言
- 3.1 栈
- 3.1.1 抽象数据类型栈的定义
- 3.1.2 栈的表示和实现
- 3.2 栈的应用举例
- 3.2.1 数制转换
- 3.2.2 括号匹配的检验
- 3.2.3 行编辑程序
- 3.2.4 迷宫求解
- 3.2.5 表达式求值
- 3.3 栈与递归的实现
- 3.4 队列
- 3.4.1 抽象数据类型队列的定义
- 3.4.2 链队列--队列的链式表示和实现
- 3.4.3 循环队列 -- 队列的顺序表示和实现
- 3.5 离散事件模拟
前言
栈和队列是两种重要的线性结构,从数据结构角度来看,栈和队列也是线性表。
其特殊性在于栈和队列的基本操作是线性表操作的子集,他们是操作受限的线性表,因此可以称为限定性的数据结构。
但是从数据类型角度来看,他们是和线性表大不相同的两类重要的抽象数据类型。
由于他们广泛的
3.1 栈
3.1.1 抽象数据类型栈的定义
栈(STACK):
是限定仅在表尾进行插入或者删除操作的线性表。因此,对栈来讲,表尾端有及其特殊的含义,称为栈顶(TOP)。响应地,表头端称为栈底(bottom)。不含有任何元素的空表称为空栈。
假设栈 S=(a1 ,a2 ,a3, . . . ,an),则称a1为栈底元素, an为栈顶元素。
栈中的元素是按照 a1 ,a2 ,a3, . . . ,an 的顺序进行进栈的,按照 an , . . . , a3 , a2 ,a1 的顺序进行出栈。
换句话说就是: 栈的修改是按照 后进先出的原则进行的。因此,栈又称为 后进先出 ( last in first out )
可以用一张比较形象的图进行表示:
就像铁路调度站一样,先进栈的最后出栈。还有一个比较经典的例子就是手枪的弹夹,先入后出。因为上面抽象出来的模型都是只有一端进行进出。
3.1.2 栈的表示和实现
栈的基本操作主要是: 栈的初始化,在栈顶进行插入和删除,判空以及取栈顶元素等 ,下面给出栈的抽象的数据类型的定义:
ADT Static {数据对象:数据关系:基本操作:InitStatic(&S); // 操作结果:构造一个空栈S DestroyStatic(&S); // 初试条件 :栈 S 已经存在。 操作结果 : 销毁栈 SClearStatic(); // 初始条件 : 栈 S已经存在。 操作结果 : 将S清为空栈StaticEmpty(); // 初始条件 : 栈 S已经存在。 操作结果 : 若存在的栈S 为空栈返回TRUE ,否则返回的是 FALSE。StaticLength(); // 初始条件 : 栈 S已经存在。 操作结果 : 返回栈S的元素个数,也就是栈的长度GetTop(S,&e); // 初始条件 : 栈 S已经存在并且非空。 操作结果 :用E返回S的栈顶元素。Push(&S,e); // 初始条件 : 栈 S已经存在。 操作结果 :插入元素e为新的栈顶元素。 也是就是俗称的入栈Pop(&S,&e); // 初始条件 : 栈 S已经存在并且非空。 操作结果 :删除S的栈顶元素,并使用e返回其值。StaticTraverse(S,visit()); // 初始条件 : 栈 S 已经存在并且非空。// 操作结果:从栈顶到栈底依次对每一个元素调用函数visit(),一旦函数失败,则操作失败。 }ADT Static
3.2 栈的应用举例
3.2.1 数制转换
3.2.2 括号匹配的检验
3.2.3 行编辑程序
3.2.4 迷宫求解
3.2.5 表达式求值
3.3 栈与递归的实现
3.4 队列
和栈相反的,队列(Queue)是一种先进先出( first in first out 缩写为FIFO)的线性表。(在单片机中,串口接收消息时候,FIFO 使用的会比较多)
它只允许在表的一端进行插入,而在另外的一端进行删除元素。这个和我们日常生活中的排队是一样的,最早进入队列的元素最先离开。
在队列中,允许插入元素的一端叫做队尾(rear),允许进行删除的一端叫做队头(front)。
假设队列为Q =(a1 ,a2 ,a3 ,a4 … … an), 那么a1就是队头(front),an就是队尾(rear)。
队列是按照 a1 a2 a3 … an 的顺序进队,出队的时候,也是按照 a1 a2 a3 … an 的顺序出队。
队列在程序设计中也经常出现,一个最典型的例子就是操作系统中的作业排队。
在允许多道程序运行的计算机系统中,同时有几个作业运行,如果运行的结果都需要通过通道输出,
那就要按请求输出的先后次序排队。每当通道传输完毕可以接受新的输出任务时,队头的作业先从队列中退出作输出操作。
凡是申请输出的作业都从队尾进入队列。队列的操作与柱的操作类似,也有8个,不同的是删除是在表的头部(即队头)进行。
3.4.1 抽象数据类型队列的定义
ADT queue
{数据对象:D={ai |ai∈ElemSet, i = 1,2,3,...n , n>=0}数据关系:R1 = { < a(i-1),ai > | a(i-1),ai∈D , i = 1,2,3,...n , n>=0} 基本操作:InitQueue(&Q)操作结果 :构造一个新的队列Q。DestoryQueue(&Q)初试条件 :队列Q已经存在操作结果 :队列Q 被销毁,不复存在ClearQueue(&Q)初始条件 :队列Q已经存在操作结果 : 将Q清为空队列QueueEmpty(Q)初试条件 : 队列Q已经存在 操作结果 : 若 Q 为空队列 , 则返回TRUE ,否则返回 FALSEQueueLength(Q)初试条件 : 队列Q已经存在操作结果 : 返回 Q 中元素的个数,也即是队列的长度GetHead(Q,&e)初试条件 : 队列Q已经存在,并且为非空操作结果 : 用e返回队列中的头元素EnQueue(&Q,e)初试条件 : 队列Q已经存在操作结果 : 插入元素e为Q的新的队尾元素DeQueue(&Q,&e)初试条件 : Q为非空队列操作结果 : 删除 Q 的对头元素,并用 e 返回其值QueueTraverse(Q,visit())初试条件 : 队列Q已经存在,并且为非空操作结果 : 从队头到队尾,依次对Q的每个结点中的元素进行调用 Visit()函数,一旦visit()失败,则操作失败。
}ADT queue
3.4.2 链队列–队列的链式表示和实现
和线性表比较类似,队列也可以有两种存储表示:
用链表表示的队列简称为链队列,如图3.10所示。
一个链队列显然需要两个分别指示队头和队尾的指针(分别称为头指针和尾指针)才能惟一确定。
这里,和线性表的单链表一样,为了操作方便起见,我们也给链队列添加一个头结点,并令头指针指向头结点。
由此,空的链队列的判决条件为头指针和尾指针均指向头结点,如图3.11(a)所示。
链队列的操作即为单链表的插人和删除操作的特殊情况﹐只是尚需修改尾指针或头指针,
图3.11(b)~(d)展示了这两种操作进行时指针变化的情况。
下面给出链队列类型的模块说明:
/*=============================* 队列的顺序存储结构(顺序队列)==============================*/#include "SqQueue.h" //**▲03 栈和队列**///** 初始化** 构造一个空的顺序队列。* 初始化成功则返回OK,否则返回ERROR。**【注】* 这里的队列是循环队列*/
Status InitQueue(SqQueue* Q) {if(Q == NULL) {return ERROR;}(*Q).base = (QElemType*) malloc(MAXQSIZE * sizeof(QElemType));if(!(*Q).base) {exit(OVERFLOW);}(*Q).front = (*Q).rear = 0;return OK;
}/** 销毁(结构)** 释放循环顺序队列所占内存。*/
Status DestroyQueue(SqQueue* Q) {if(Q == NULL) {return ERROR;}if((*Q).base) {free((*Q).base);}(*Q).base = NULL;(*Q).front = (*Q).rear = 0;return ERROR;
}/** 置空(内容)** 只是清理循环顺序队列中存储的数据,不释放顺序队列所占内存。*/
Status ClearQueue(SqQueue* Q) {if(Q == NULL || (*Q).base == NULL) {return ERROR;}(*Q).front = (*Q).rear = 0;return OK;
}/** 判空** 判断循环顺序队列中是否包含有效数据。** 返回值:* TRUE : 循环顺序队列为空* FALSE: 循环顺序队列不为空*/
Status QueueEmpty(SqQueue Q) {// 队列空的标志if(Q.front == Q.rear) {return TRUE;} else {return FALSE;}
}/** 计数** 返回循环顺序队列包含的有效元素的数量。*/
int QueueLength(SqQueue Q) {if(Q.base == NULL) {return 0;}// 队列长度return (Q.rear - Q.front + MAXQSIZE) % MAXQSIZE;
}/** 取值** 获取队头元素,将其存储到e中。* 如果可以找到,返回OK,否则,返回ERROR。*/
Status GetHead(SqQueue Q, QElemType* e) {// 队列空的标志if(Q.base == NULL || Q.front == Q.rear) {return ERROR;}*e = Q.base[Q.front];return OK;
}/** 入队** 将元素e添加到队列尾部。*/
Status EnQueue(SqQueue* Q, QElemType e) {if(Q == NULL || (*Q).base == NULL) {return ERROR;}// 队列满的标志(会浪费一个空间来区分队列空和队列满)if(((*Q).rear + 1) % MAXQSIZE == (*Q).front) {return ERROR;}// 入队(*Q).base[(*Q).rear] = e;// 尾指针前进(*Q).rear = ((*Q).rear + 1) % MAXQSIZE;return OK;
}/** 出队** 移除队列头部的元素,将其存储到e中。*/
Status DeQueue(SqQueue* Q, QElemType* e) {if(Q == NULL || (*Q).base == NULL) {return ERROR;}// 队列空的标志if((*Q).front == (*Q).rear) {return ERROR;}// 出队*e = (*Q).base[(*Q).front];// 头指针前进(*Q).front = ((*Q).front + 1) % MAXQSIZE;return OK;
}/** 遍历** 用visit函数访问队列Q*/
Status QueueTraverse(SqQueue Q, void(Visit)(QElemType)) {int i;if(Q.base == NULL) {return ERROR;}for(i = Q.front; i != Q.rear; i = (i + 1) % MAXQSIZE) {Visit(Q.base[i]);}printf("\n");return OK;
}
3.4.3 循环队列 – 队列的顺序表示和实现
3.5 离散事件模拟
数据结构严蔚敏--第三章--栈和队列相关推荐
- (王道408考研数据结构)第三章栈和队列-第三节1:栈的应用之括号匹配问题和表达式问题(前缀、中缀和后缀)
前面我们就说过,栈是一种先进后出的线性表,这种先进后出的特性就决定了它在一类场合或问题中会经常被用到--递归.考研数据结构中所涉及的利用栈结构解决递归问题或者考察栈结构特性的问题主要有这么几类 括号匹 ...
- 数据结构-第三章-栈和队列(5)-链队
数据结构 ⚡️数据结构-第一章 ⚡️抽象数据类型案例 ⚡️数据结构-第二章(1)-线性结构 ⚡️数据结构-第二章(2)-线性表的顺序表示和实现 ⚡️数据结构-第二章(3)-顺序表(含代码) ⚡️数据结 ...
- C语言数据结构【手抄版】第三章 栈和队列
注意:文中彩色代码均在Visual Studio 2022编译器中编写,本文为C语言数据结构手抄版,文中有部分改动,非原创. 目录 注意:文中彩色代码均在Visual Studio 2022编译器中编 ...
- C语言数据结构-第三章栈和队列-电大同步进度
第三章栈和队列简介 从数据结构角度看,栈和队列是两种重要的线性结构,是一类操作受限制的特殊线性表,其特殊性在于限制插入和删除等运算的位置. 堆栈,限制用户只能在指定的一端插入和删除元素,因此具有后进先 ...
- 王道考研408 数据结构 第三章 栈、队列与数组
第三章 栈.队列与数组 3.1 栈 3.1.03 假设以I和O分别表示入栈和出栈操作.栈的初态和终态均为空,入栈和出栈的操作序列可表示为仅由I和O组成的序列,称可以操作的序列为合法序列,否则称为非法序 ...
- 第三章栈和队列-作业题
第三章栈和队列-作业题 1.栈和列队的基本概念 6-1 使用栈完成回文判断 (12 分) 6-2 判断表达式中括号是否匹配 (12 分) 6-3 队列的操作集合(带尾指针的循环链表) (18 分) 6 ...
- 数据结构(C语言版) 第 三 章 栈与队列 知识梳理 + 作业习题详解
目录 一.栈 0.栈的基本概念 1.栈的实现 2.栈与递归 3.Hanoi塔问题 二.队列 0.队列的基本概念 1.队列的实现 2.循环队列 2.1循环队列的相关条件和公式: 3.链队列 4.链队列完 ...
- 王道数据结构课代表 - 考研数据结构 第三章 栈和队列 究极精华总结笔记
本篇博客是考研期间学习王道课程 传送门 的笔记,以及一整年里对数据结构知识点的理解的总结.希望对新一届的计算机考研人提供帮助!!! 关于对 栈和队列 章节知识点总结的十分全面,涵括了<王道数 ...
- (王道408考研数据结构)第三章栈和队列-第一节:栈基本概念、顺序栈和链栈基本操作
文章目录 一:栈基本概念 (1)栈的定义 (2)压栈和出栈 (3)进栈出栈变化形式 (4)栈的操作 二:栈的顺序存储结构及其操作实现 (1)顺序栈的定义 (2)进栈 (3)出栈 (4)读取栈顶元素 ( ...
- 数据结构——第三章 栈和队列
一.单选题(共18题,55分) 1.栈结构通常采用的两种存储结构是( ). A. 顺序存储结构和链表存储结构. B. 散列方式和索引方式. C. 链表存储结构和数组. D. 线性链表结构和非线性 ...
最新文章
- react mysql增删改查_react增删改查
- web自动化如何在不同浏览器运行_Web自动化测试:元素的基础操作和浏览器基础操作...
- AI时代的神马搜索!神马智能对话技术深度解读
- java url参数转换:_提示:通过URL激活并发送参数
- java 调用mysql视图_如何在java spring POJO类上注入和使用mysql视图代替表 . 是否可以使用视图...
- JavaScript 根据两点的经纬度坐标,计算实际的直线距离
- 安装NET Framework 错误代码0x800F081F怎么解决
- MFC模态对话框和非模态对话框使用
- 产品结构图 VS 信息结构图 VS 功能结构图(附案例)
- 大学的c语言课程难度,大学挂科率最高的4门课程,学霸也担心挂科,有你学过的课程吗?...
- 健康生活 多用肥皂少用洗涤剂
- 再聊聊Linux IO
- 阿里云KMS创建应用接入点
- 软件测试bug分析定位技巧
- Could not delete path ‘D:\AndroidStudioProjects\LargeScreen\app\build\generated\source\r\debug\andro
- 【渝粤教育】国家开放大学2018年秋季 2370T汽车故障诊断技术(A) 参考试题
- 短视频批量伪原创破解 苹果手机md5视频修改工具下载
- 条件式变换自编码机(conditional variational autoencoders)学习笔记(一)
- html格子像素画,canvas像素画板的实现代码
- 快速给多个视频添加相同滚动字幕