完整数据结构详细教案栈和队列.docx

上传人:b****5 文档编号:7886530 上传时间:2023-01-26 格式:DOCX 页数:11 大小:22.63KB
下载 相关 举报
完整数据结构详细教案栈和队列.docx_第1页
第1页 / 共11页
完整数据结构详细教案栈和队列.docx_第2页
第2页 / 共11页
完整数据结构详细教案栈和队列.docx_第3页
第3页 / 共11页
完整数据结构详细教案栈和队列.docx_第4页
第4页 / 共11页
完整数据结构详细教案栈和队列.docx_第5页
第5页 / 共11页
点击查看更多>>
下载资源
资源描述

完整数据结构详细教案栈和队列.docx

《完整数据结构详细教案栈和队列.docx》由会员分享,可在线阅读,更多相关《完整数据结构详细教案栈和队列.docx(11页珍藏版)》请在冰豆网上搜索。

完整数据结构详细教案栈和队列.docx

完整数据结构详细教案栈和队列

(完整)数据结构详细教案——栈和队列

编辑整理:

 

尊敬的读者朋友们:

这里是精品文档编辑中心,本文档内容是由我和我的同事精心编辑整理后发布的,发布之前我们对文中内容进行仔细校对,但是难免会有疏漏的地方,但是任然希望((完整)数据结构详细教案——栈和队列)的内容能够给您的工作和学习带来便利。

同时也真诚的希望收到您的建议和反馈,这将是我们进步的源泉,前进的动力。

本文可编辑可修改,如果觉得对您有帮助请收藏以便随时查阅,最后祝您生活愉快业绩进步,以下为(完整)数据结构详细教案——栈和队列的全部内容。

 

数据结构教案

第三章栈和队列

第3章栈和队列

3.1栈的基本概念

3.1.1栈的抽象数据类型定义

1、栈的逻辑特征

1)限定在表尾进行插入或删除操作的线性表;

2)栈顶—-表尾端;栈底-—表头端

3)后进先出的线性表

2、抽象数据类型的定义

ADTStack{

数据对象:

D={ai|ai∈ElemSet,i=1,2,…,n,n≥0}

数据关系:

R={R1},R1={〈ai-1,ai〉|ai-1,ai∈D,i=2,3,…,n}

基本操作:

InitStack(&S)

操作结果:

构造一个空的栈S

DestroyStack(&S)

初始条件:

栈S已存在

操作结果:

销毁栈S

ClearStack(&S)

初始条件:

栈S已存在

操作结果:

将栈S重置为空栈

StackEmpty(S)

初始条件:

栈S已存在

操作结果:

若S为空栈,则返回TRUE,否则返回FALSE

StackLength(S)

初始条件:

栈S已存在

操作结果:

返回栈S中数据元素的个数

GetTop(S,&e)

初始条件:

栈S已存在且非空

操作结果:

用e返回S中栈顶元素

Push(&S,e)

初始条件:

栈S已存在

操作结果:

插入元素e为新的栈顶元素

Pop(&S,&e)

初始条件:

栈S已存在且非空

操作结果:

删除S的栈顶元素,并用e返回其值

StackTraverse(S,visit())

初始条件:

栈S已存在且非空

操作结果:

从栈底到栈顶依次对S的每个数据元素调用函数visit().一旦visit()失败,则操作失败

}ADTStack

思考:

栈的取元素、插入、删除操作与线性表的相应操作有何区别,为什么?

3.1.2顺序栈

1、增量式顺序栈的定义

#defineSTACK_INIT_SIZE100/*存储空间的初始分配量*/

#defineSTACKINCREMENT10/*存储空间的分配增量*/

typedefstruct{

ElemType*base;/*栈底指针*/

ElemType*top;/*栈顶指针(栈顶元素的下一个位置)*/

intstacksize;/*当前分配的存储容量*/

}SqStack;

1)和顺序表一样采用增量式的空间分配;

2)操作和栈顶相关:

插入操作(入栈):

将待插元素插入到栈顶元素的下一个位置;

删除操作(出栈):

删除栈顶元素;

取元素操作:

取栈顶元素的值.

各操作的操作位置与栈顶元素的位置或其下一个位置相关,希望在O

(1)时间内能获取操作位置,故可设置专门的栈顶指针top.

3)约定:

top指向栈顶元素的下一个位置(便于表示空栈)。

4)栈顶的初始化:

S。

top=S.base(在上述3)约定下的空栈形式),

5)栈空:

S.base==S.top,栈满:

S。

top-S.base>=S.stacksize

6)入栈:

*S。

top++=e,出栈:

e=*—-S。

top

注意:

4),5),6)步受3)制约。

约定不同,相应的判定和处理也不一样.

如假设top就指向栈顶元素,此时4),5),6)如何?

2、取栈顶元素GetTop_Sq

1)算法设计

参数:

顺序栈S、取得的栈顶元素&e

分析:

由于top指向栈顶元素的下一个位置,因此实际的栈顶元素的位置应是top-1;

栈非空时,此操作有效.

算法1

StatusGetTop_Sq(SqStackS,ElemType&e){

/*判断栈是否为空*/

if(S。

base==S.top)returnERROR;

e=*(S.top-1);

returnOK;

3、入栈操作Push_Sq

1)算法设计

参数:

顺序栈&S、插入元素e

分析:

插入位置为栈顶元素的下一个,无须判断位置的合法性;

上溢即栈满的条件需要判断,由于是增量式分配,故栈满时需要重新申请空间;

算法2

StatusPush_Sq(SqStack&S,ElemTypee){

/*判断栈是否为满*/

if(S.top–S。

base〉=S.stacksize){

/*栈满,追加空间*/

S.base=(ElemType*)realloc(S.base,

(S。

stacksize+STACKINCREMENT)*sizeof(ElemType));

if(S。

base==NULL)exit(OVERFLOW);

S.top=S。

base+S.stacksize;

S.stacksize+=STACKINCREMENT;

*S。

top++=e;

returnOK;

2)算法分析-—时间T(n)=O

(1)

4、出栈操作Pop_Sq

1)算法设计

参数:

顺序栈&S、删除的栈顶元素&e

分析:

在栈非空时,删除栈顶元素

算法3

StatusPop_Sq(SqStack&S,ElemType&e){

/*判断栈是否为空*/

if(S.base==S。

top)returnERROR;

e=*(--S。

top);/*注意与GetTop()的区别*/

returnOK;

}

2)算法分析——时间T(n)=O

(1)

3.1.3链栈

与链表类似,只是链表的头指针即为栈顶指针.因其操作均在栈顶进行,故可以不引入头结点。

思考:

在链栈下的入栈、出栈以及取栈顶元素的操作的算法如何写?

3.2栈的应用

3.2.1数制转换:

将十进制数N转换成其他d进制数

算法思想:

N=(Ndivd)×d+Nmodd

1)将N%d的结果保存,

2)N=N/d,

3)若N==0结束,否则继续1)。

保存的余数从先到后依次表示转换后的d进制数的低位到高位,而输出是由高位到低位的,因此必须定义先进后出的线性表——栈来保存;当全部的余数求出后,通过逐个出栈输出d进制数.

3.2.2括号匹配的检验

算法思想:

从左至右扫描表达式,遇左括号入栈,遇右括号与栈顶元素比较:

若左右括号匹配,则继续扫描;否则说明不匹配,结束。

在上述操作中,若栈为空,或扫描结束后栈不为空,均说明不匹配。

3.2.3行输入处理程序

处理规则:

遇‘#’退一格;遇‘@’退一行

算法思想:

引入栈,保存终端输入的一行字符(逐行处理);

遇‘#'退一格—-出栈一次

遇‘@’退一行——清栈

步骤:

1)初始化栈S

2)读入字符ch

3)ch!

=EOF

3。

1)ch!

=EOF&&ch!

=’\n’

3。

1。

1)ch为‘#’:

Pop(S,c),转3.1.4)

3.1。

2)ch为‘@’:

ClearStack(S),转3。

1.4)

3.1.3)ch为其他:

Push(S,ch),转3.1.4)

3。

1。

4)再读入字符ch,继续3。

1)

3。

2)处理完一行,清空栈

3.3)如ch!

=EOF,读入字符ch,继续3)

3.2.4迷宫求解

问题:

找从“入口"到“出口"的路径(所经过的通道方块)

分析:

1)方块的表示—-坐标,当前的状态(障碍、未走的通路、已走的通路);

2)已走的路径:

A.路径中各方块的位置及在路径中的序号;

B.从各方块出发已探索的方向,注意不能重复(可约定按东、南、西、北的方向顺次探索);

C.从当前方块无路可走时,将已走路径回退一个方块,继续探索其他未走的方向

栈—-存储已走的通道块

3.2.5表达式求值

1、问题描述

·只包含+,-,*,/四个双目运算符,且算符本身不具有二义性;

·三个运算规则→运算符优先关系(考虑算符本身的优先级和结合性);

·只有’(’==’)',’#'=='#’;

·假设输入的是一个合法的表达式。

2、算法思想

引入OPTR和OPND两个栈

初始:

OPTR有一个元素'#',OPND为空

读入一字符c

c=='#':

return(GetTop(OPND))

c非运算符:

Push(OPND,c)

c运算符:

t=GetTop(OPTR),比较t和c的优先关系

t

Push(OPTR,c)

t==c:

Pop(OPTR,x)

t>c:

Pop(OPTR,theta);Pop(OPND,b);Pop(OPND,a);

x=Operate(a,theta,b);Push(OPND,x);

继续读入字符处理。

3.3栈与递归的实现

1、递归定义

直接或间接地调用自身的函数,称为递归函数。

如右图所示,递归表现为:

在该函数的所有可能执行路径中,存在一条由于调用自身或其它函数所导致的环路路径;为确保函数最终在有限的时间内执行完毕,必须在环路中存在一个出口,即当某种条件成立时,不必执行环路,而直接执行一条通向结束的非环路线.

2、递归应用

1)递归应用类型

·递归定义的数学问题

·具有递归特性的数据结构,其操作可以递归地表示

·其它一些问题

2)递归应用的特点

对于一个问题,当问题规模很大时,往往难于直接求解,此时:

·将大问题分解成若干小问题

·考虑如何利用这些小问题的解构成大问题的解

·避免陷入考虑如何求解小问题

这种分解、合成的方法就是递归求解中的递归方法;

另外,递归应用要注意避免陷入死循环,递归必须有出口,即要确立递归的结束条件,给出此时的直接求解方法.

3)递归应用举例

Hanoi塔问题

3、递归的实现

1)系统的处理

(1)调用前

现场保护,被调用函数的局部变量的空间分配,控制转移至被调用的函数入口.

(2)调用后

保存计算结果,释放被调函数的数据区,控制转移回调用处。

2)实现—-栈

“后调用先返回”。

系统利用递归工作栈记录各层调用的现场信息。

3.4队列的基本概念

3.4.1队列的抽象数据类型定义

1、队列的逻辑特征

1)先进先出的线性表

2)队头:

允许删除的一端;队尾:

允许插入的一端

3)应用举例:

操作系统的作业排队

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

ADTQueue{

数据对象:

D={ai|ai∈ElemSet,i=1,2,…,n,n≥0}

数据关系:

R={R1},R1={〈ai-1,ai〉|ai-1,ai∈D,i=2,3,…,n}

基本操作:

InitQueue(&Q)

操作结果:

构造一个空队列Q

DestroyQueue(&Q)

初始条件:

队列Q已存在

操作结果:

销毁队列Q

ClearQueue(&Q)

初始条件:

队列Q已存在

操作结果:

将队列Q重置为空队列

QueueEmpty(Q)

初始条件:

队列Q已存在

操作结果:

若Q为空队列,则返回TRUE,否则返回FALSE

QueueLength(Q)

初始条件:

队列Q已存在

操作结果:

返回队列Q中数据元素的个数

GetHead(Q,&e)

初始条件:

队列Q已存在且非空

操作结果:

用e返回Q中队头元素

EnQueue(&Q,e)

初始条件:

队列Q已存在

操作结果:

插入元素e为Q的新的队尾元素

DeQueue(&Q,&e)

初始条件:

队列Q已存在且非空

操作结果:

删除Q的队头元素,并用e返回其值

QueueTraverse(Q,visit())

初始条件:

队列Q已存在且非空

操作结果:

从队头到队尾依次对Q的每个数据元素调用函数visit()。

一旦visit()失败,则操作失败

}ADTQueue

3、双端队列

1)限定插入和删除在表的两端进行,应用举例:

铁道转轨网络

2)输出受限的双端队列和输入受限的双端队列

3)双端队列→两个栈底相邻接的栈:

限定双端队列,从某端点插入的元素只能从该端点删除。

3.4.2链队列

1、链队列的定义

typedefstructQNode{

ElemTypedata;

structQNode*next;

}QNode,*QueuePtr;

typedefstruct{

QueuePtrfront;/*队头指针,指向头元素*/

QueuePtrrear;/*队尾指针,指向队尾元素*/

}LinkQueue;

1)引入队头指针、队尾指针:

在O

(1)时间内找到操作结点

2)引入头结点:

队尾插入时,使队空和队不空的结点表示一致

3)队空的判断:

头、尾指针均指向头结点

4)队满的判断转变成对申请空间是否成功的判断。

2、类型说明

操作实现:

初始化、入队、出队

注意:

队空的判断、入队、出队依赖于队列的表示及其约定。

进一步考虑:

若无头结点,此时队列的初始化、入队、队空的条件、出队等如何表示与实现?

3.4.3循环队列

1、循环队列的定义

采用顺序表存储,约定front指向队列头元素,rear指向队尾元素的下一位置。

#defineMAXQSIZE100/*最大队列长度*/

typedefstruct{

ElemType*base;/*存储空间*/

intfront;/*头指针,指向队列的头元素*/

intrear;/*尾指针,指向队尾元素的下一个位置*/

}SqQueue;/*非增量式的空间分配*/

2、操作实现

1)空队:

Q。

front=Q.rear=0;

2)入队:

判断是否队满,非队满时,Q。

rear位置放新插入的元素,Q.rear++

3)出队:

判断是否队空,非队空时,Q.front位置为待删除的元素,Q.front++

4)队空条件:

Q.front==Q.rear

5)队满条件:

Q.rear==MAXQSIZE—1

问题:

存在假上溢(由于出队操作,队列空间的上部可能存在空闲空间)

3、假上溢的解决

将队列假想为首尾相接的环,即循环队列。

1)入队:

……,Q.rear=(Q.rear+1)%MAXQSIZE

2)出队:

……,Q。

front=(Q.front+1)%MAXQSIZE

3)队空条件:

Q。

front==Q。

rear,由于出队Q。

front追上了Q.rear

4)队满条件:

Q.front==Q。

rear,由于入队Q。

rear追上了Q.front

问题:

队空和队满的判断条件一样

4、如何区分队空和队满

1)设标志位:

不足在于需要额外对标志位的判断及维护

2)在队列的结构中引入长度成员,在初始化队列、入队、出队操作中维护这个成员。

3)少用一个元素空间,即队满的条件如下

(Q。

rear+1)%MAXQSIZE==Q。

front

进一步思考:

1)对比4中所列的3种方法在队列操作中处理的不同。

2)若循环队列数组的下标起始为—3,1或3时,如何判断队空、队满,如何实现入队、出队?

3.5队列与栈的应用

3.5.1离散事件模拟

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 农林牧渔 > 林学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1