没有合适的资源?快使用搜索试试~ 我知道了~
山东大学《数据结构》讲义03栈和队列.docx
0 下载量 199 浏览量
2022-12-15
23:25:42
上传
评论
收藏 55KB DOCX 举报
温馨提示
试读
24页
山东大学《数据结构》讲义03栈和队列.docx
资源推荐
资源详情
资源评论
第三章栈和队列
内容概述
从数据结构角度来看,栈和队列是两种特殊的线性表,其特殊性表达在它们的 基本
操作是线性表操作的子集,因此它们是限定性的数据结构。从抽象数据类型 角度来看,
它们是不同于线性表的两类重要的抽象数据类型。由于栈和队列在实 际应用中的广泛
性和其操作的特殊性,本章从栈和队列的抽象数据类型定义、栈 和队列的顺序表示与
实现、栈和队列的链式表示与实现、栈和队列的应用等几个 方面进行专门讨论。
重点与难点
重点为栈和队列的运算,循环队列。难点为栈与递归的关系,栈与队列的应用。
思考.栈是具有什么特性的线性表?
1 .队列是具有什么特性的线性表?
2 .分析栈与递归的关系。
3 .假设一个栈的入栈序列是1, 2, 3,…,n,其输出序列为pl,p2,p3,…,pn, 假设 pl=n,那
么 pi=?
4 .设有一个顺序栈S,元素sl,s2,s3,s4,s5,s6依次进栈,如果6个元素的出栈 顺序为
s2,s3,s4,s6,s5
z
sl,那么顺序栈的容量至少应为多少?
5 .为什么要循环队列?在循环队列中队列空、满的评定标准是什么?
6 .利用两个栈模拟一个队列的入队、出队、判断队空等运算。
第一节栈栈是一种具有''后进先出〃特性的线性表。这种特性对其操作有何影响呢?
其存储 结构相对于一般线性表又会有哪些变化?本节将从栈的定义、抽象类型定义、
栈 的顺序与链式存储结构等方面入手解答上述问题。
1、栈的定义1、栈的定义
栈(Stack)又称堆栈,是一种特殊的线性表,可定义为插入、删除和访问只能 在某一端
进行的线性数据结构。堆栈允许插入、删除和访问的一端称为栈顶
(Top),另一端称为栈底(Bottom) o栈顶的第一个元素被称为栈顶元素。不 含数据元素
的空表称为空栈。
向一个栈插入新元素又称为进栈或入栈,它是把该元素放到栈顶元素的上面,使 之成
为新的栈顶元素;从一个栈删除元素又称为出栈或退栈,它是把栈顶元素删 除掉,使
其下面的相邻元素成为新的栈顶元素。
堆栈的性质决定它的数据是按''先进后出〃的顺序被访问,即最先存储的元素最后 被
访问、删除,最后存储的元素最先被访问、删除,所以栈也称为、'LIFO〃
(Last_In,First_Out) □栈的模型在日常生活中是普遍存在的,如铁路列车调度系统
等,在计算机科学中, 栈是一种非常有用的数据结构。实际上,TurboC在将参数传
递给函数时,就使 用堆栈。
我们应该注意到:栈是一种动态的数据结构,也就是说,随着对栈进行插入和删 除等
不同的操作,其结点个数、内容等将会不断发生变化。
径。如图35 图中路径为该迷宫探索的全过程,包含退回至「前一通道块〃的操 作过
程。
本算法的描述如下:
StatusMazeRath(MazeTypemaze,RosTypestart,PosTypeend){〃假设迷宫maze
中存在从入口 start到出口 end的通道,那么求得一条路径存放在
栈中(从〃栈底到栈顶),并返回TRUE;否那么返回FALSEInitStack(S);
curpos=start;〃设定''当前位置〃为''入 口 位置”
curst叩二1;〃探藁第一步do{
if(Pass(curpos,maze)){〃当前位置可以通过,即是未曾走过的通道块
FootPrint(cu rpos,maze); 〃留下足迹
e=(curstep,curpos,l);
Push(S,e);〃加入路径
if(curpos==end)retu「n(TRUE);〃到达终点(出 口)
curpos=NextPos(curpos
z
1); 〃下一位置是当前位置的东邻
cu rstep++;〃探集下一步
)//if
else{
〃当前位置不能通过
if(!StackEmpty(S)){
Pop(S,e);
while(e,di==4&&!StackEmpty(S)){
Pop ⑸ e);}//while
if(e.di<4){
e.di++; 〃换下一个方向探索
Push(S,e);
curpos=NextPos(e.pos,e.di);
〃设定当前位置是该新方向上的通道块
}//if(e.di<4)
}//if(!StackEmpty(S))
}//else
}while(!StackEmpty(S));
return(FALSE);
}//MazePath
StatusPass(PosTypepos,MazeTypemaze){
if(maze[pos.x] [pos.y]==0)returnOK;
elsereturnO;
)
voidFootPnnt(PosTypepos,MazeTypemaze){
maze[pos.x][pos.y]=2;//标记为已走过该方块
voidNextPos( PosT y pe&pos, i ntd i){
switch(di){
casel:(pos).y+=1; break;〃向东
case2:(pos).x+=1; break;〃向南
case3 :(pos) ,y-=l;break;〃向西
ca se4:(pos) .x-=l;break;〃向北
)
)算法3-13迷宫求解算法
4、栈与递归实现的关系4、栈与递归实现的关系
栈还有一个重要应用是在程序设计语言中实现递归。一个直接调用自己或通 过一
系列的调用语句间接地调用自己的函数,称作递归函数。
在程序设计中,递归是一个非常重要的工具。第一,有很多数学函数是通过 递归
定义的,比方阶乘函数:
和 2 阶 Fibonacci 数歹(J:
等;第二,由于有的数据结构本身固有的递归特性,它们的操作可以通过递归进 行描
述,比方二叉树、广义表等;第三,有的问题虽然本身不具备明显的递归结 构,但是
运用递归进行问题的求解相比迭代方法更简单,比方八皇后问题、Hanoi 塔问题等。
作为递归函数,在其执行过程中,需要屡次进行自我调用。为了理解这个问 题,
我们先看任意两个函数之间是如何进行调用的。在高级语言编制的程序中, 调用函数
和被调用函数之间的链接及信息交换需要通过栈来进行。通常,当在一 个函数的运行
期间调用另一个函数时,系统在运行被调用函数前要先完成以下工 作:(1)将所有的实
在参数、返回地址等信息传递给被调用函数保存;(2)为 被调用函数的局部变量分配存
储区;(3)将控制转移到被调用函数的入口。同 样,从被调用函数返回调用函数前,系
统也需要完成一些工作:(1)保存被调 用函数的计算结果;(2)释放被调用函数的数据
区;(3)依照被调用函数保存 的返回地址将控制转移到调用函数。当有多个函数构成嵌套
调用时,按照''后调 用先返回〃的原那么,上述函数之间的信息传递和控制转移必须
通过栈来实现。系 统设置一个栈作为整个程序运行时所需的数据空间,每调用一个函
数就为其在栈 顶分配一个存储区,每从一个函数退出时就释放其存储区,那么当前正
运行的函数 的数据区必在栈顶。实际上,在调用函数和被调用函数之间不一定传递参
数的值, 也可以传递参数的地址。通常,每个程序设计语言都有它自己的参数传递方法。
下面举一个例子来具体说明函数调用的工作原理。在图3,6(c)所示的程序段中, 主函数
main中调用了函数first,而在函数first中又调用了函薮second,那么当前 系统正在执行
函数second中某个语句时栈的状态如图3.6(a),从函数second 退出后正执行函数first中
某个语句时栈的状态如图3.6(b)。注意,图中语句标 号表示返回地址。
一个递归函数的运行过程类似于多个函数的嵌套调用,只是调用函数和被调用函 数是
同一个函数,因此,和每次调用相关的一个重要概念是递归函数运行的''层 次假设调
用该递归函数的主函数为第0层,那么从主函数调用递归函数为进入 第1层;一般地,
从第i层递归调用本函数为进入''下一层〃,即第i+1层。反之, 从第i+1层递归退出返
回至''上一层〃,即第i层。
5、汉诺塔问题的算法5、汉诺塔问题的算法
(1)问题的提出
19世纪,欧洲出现了一个称为''汉诺塔〃的游戏,该游戏表示(毫无疑问是伪 造
的)Brahma寺庙地下通道中的一个任务。在世界产生初期,牧师得到一个镶 嵌着3根钻
石针的黄铜平台。第一根针上堆积着64个金圆盘,每一个金圆盘比 它下面的金圆盘稍
微小一些(在欧洲流行的特殊版本为具有8个纸圆盘和3个木 质柱子)。牧师被赋予一项
任务,将所有的金圆盘从第一根针移动到第三根针, 遵从的规那么是:每一次只能移动
一个金圆盘,移动过程中可以借助第二根针,金 圆盘不能放在比它小的金圆盘之上。
牧师还被告知当完成这64个金圆盘的移动 之后,将昭示着世界末日的到来。
当然,我们的任务是编写一个计算机程序,为牧师列出一个移动金圆盘的指 令列
表。这个任务可以使用如下指令:
Move(64,x
z
y,z)
指令而含义是:
将64个圆盘从塔x移动到塔z,可以使用塔y作为临时存储器。
(2)解决方案
有一个解决方案的思想是,不要将注意力集中在第一步(第一步肯定是将顶 层圆盘
移动到某处),应该主要集中在最困难的步骤上:移动底层圆盘。在上面 的63个圆盘
被移走前,无法到达最底层的圆盘,所以必须将上面的63个圆盘 都移动到塔b上,这
样才能将底层圆盘从塔a移动到塔c。这是因为每次只能移 动一个圆盘,底层圆盘(最大
的圆盘)不能在其他任何圆盘之上,因此当移动底 层圆盘时,其他任何圆盘都不能在塔
a或塔c上。这样可以将汉诺塔的算法步骤 归结为:
Move(63,a,c,b);
printf("Movedisk64fromtoweratotowerc.\n");
Move(63,b,a,c);
现在离解决方案又近了一小步,仅仅是非常小的一步,因为仍然必须描述如 何移
动上面的63个圆盘。虽然如此,这仍然是重要的一步,因为可以采用同样 的方法移动
剩下的63个圆盘(事实上,必须采用同样的方法移动,因为每一次 都有一个最大的圆
盘必须最后移动)。
这正是递归的思想。上面已经描述了递归的原理和主要步骤,将64个圆盘 的问题
转变成63个圆盘的问题,那么剩下的解决步骤在实质上和前面是相同的。 (3)算法
根据以上分析,设把n个盘子从塔x搬到塔z,用塔y作为过渡,那么编写出 递归算法
如下:
1 voidMove(intn,charx,chary,charz){if(n==l)
2 printf(
u
%d.Movedisk%dfrom%cto%c\n
,,
,++i,n
z
x,z);
〃当只有一个盘子时,直接由塔x搬到塔z后结束一次函数调用
〃其中i是初值为0的全局变量,表示搬动的步骤数。
3 else{
剩余23页未读,继续阅读
资源评论
matlab大师
- 粉丝: 2434
- 资源: 9万+
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- 本科毕业设计基于C# wpf人脸识别的考勤系统的设计与实现源码.zip
- 基于Ruoyi+uniapp实现学生考勤系统 学生考勤源码+项目说明.zip
- feae6bc968ca68a099455d8b8a8dea35
- 基于Pytorch训练CIRAR10上分类算法.zip
- Pytorch-pytorch深度学习教程之Tensorboard.zip
- 基于C++和Python开发yolov8-face作为人脸检测器dlib作为人脸识别器的人脸考勤系统源码+项目说明.zip
- Pytorch-pytorch深度学习教程之变分自动编码器.zip
- Pytorch-pytorch深度学习教程之神经风格迁移.zip
- Pytorch-pytorch深度学习教程之深度残差网络.zip
- Pytorch-pytorch深度学习教程之循环神经网络.zip
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功