栈和队列.docx

上传人:b****5 文档编号:11802542 上传时间:2023-04-02 格式:DOCX 页数:9 大小:504.36KB
下载 相关 举报
栈和队列.docx_第1页
第1页 / 共9页
栈和队列.docx_第2页
第2页 / 共9页
栈和队列.docx_第3页
第3页 / 共9页
栈和队列.docx_第4页
第4页 / 共9页
栈和队列.docx_第5页
第5页 / 共9页
点击查看更多>>
下载资源
资源描述

栈和队列.docx

《栈和队列.docx》由会员分享,可在线阅读,更多相关《栈和队列.docx(9页珍藏版)》请在冰豆网上搜索。

栈和队列.docx

栈和队列

栈和队列

 一、栈的定义

栈(Stack)是限制在表的一端进行插入和删除运算的线性表。

⏹栈顶(Top)为可进行插入、删除的一端,另一端为栈底(bottom)(base)。

⏹空栈:

表中没有元素。

Top=bottomtop与bootom指向同一位置。

假设栈S=(a1,a2,a3,…an),则a1称为栈底元素(bottom),an为栈顶元素(top)。

栈中元素按a1,a2,a3,…an的次序进栈,退栈(出栈)的第一个元素应为栈顶元素。

换句话说,栈的修改是按后进先出的原则进行的。

因此,栈称为后进先出表(LIFO)。

二、栈的基本运算

•Init_Stack(s)。

初始化栈Stack,即置Stack为空栈。

•Empty_Stack(s)。

判断Stack是否为空,若栈s为空栈,则返回值为1,否则返回值为0。

•destroy_Stack(s)销毁一个已经存在的栈

•Push_Stack(s,x)。

进栈操作。

在栈s的栈顶位置插入数据元素x。

•Pop_Stack(s,x)。

出栈操作。

若栈s不为空,将栈顶元素赋给x,并从栈中删除当前栈顶元素。

•GetTop_Stack(s,x)。

读取栈顶。

若栈s不为空,由x返回栈顶元素;当栈s为空时,结果为一特殊标志。

栈的表示

栈的顺序存储表示又称顺序栈,它是利用一组地址连续的存储单元一次存放自栈底到栈顶的数据元素,同时附设指针top指示栈顶元素在顺序栈中的位置。

三、顺序栈的类型定义(顺序栈是一块连续的存储空间,链式是用一个线性链表来表示。

#defineStackSize100//假定预分配的栈空间最多为100个元素

typedefcharDataType;//假定栈元素的数据类型为字符

typedefstruct{

DataTypedata[StackSize];

inttop;

}SeqStack;

注意:

 ①顺序栈中元素用向量存放

 ②栈底位置是固定不变的,可设置在向量两端的任意一个端点

 ③栈顶位置是随着进栈和退栈操作而变化的,用一个整型量top(通常称top为栈顶指针)来指示当前栈顶位置

四、利用顺序栈的应用举例

一个栈的输入序列为123…n,若输出序列的第一个元素是n,输出第i(1<=i<=n)个元素是()。

A.不确定      B.n-i+1     C.i   D.n-i   

设栈的输入序列是1,2,3,4,则()不可能是其出栈序列。

A.1,2,4,3,     B.2,1,3,4,   C.1,4,3,2,

D.4,3,1,2,   E.3,2,1,4,

例1:

数制转换

将十进制数N转换r进制的数。

其转换方法利用辗转相除法;以r为二进制数讲解。

算法思想如下:

1,初始化栈,初始化N为要转换的数,r为进制数

2,判断N的值,为0转4,否则N%r压入栈s中

3,用N/r代替N转2,

4,出栈,出栈序列即为结果。

具体算法如下:

TypedefintDataType;定义一个数据类型为整型

Intconversion(inN,intr)定义N和r为整型

{PSeqStacks;定义一个顺序栈

DataTypex;x为整型x用来存放栈元素

If(!

r)若r输入为0

{

Printf(“基数不能为0”);

Return(0);

}

S=Init_Seqstack();初始化栈s

If(!

s)

{

Printf(“栈初始化失败”);

Return(0);

}

While(N)

{

Push_Seqstack(s,N%r);将余数入栈

N=N/r;将N/r整除的商赋予N

}

While(!

Empty_Seqstack(s))直到栈空退出循环

{

Pop_Seqstack(s,&x)弹出栈顶元素

Printf(“%d”,x);输出栈顶元素

}

Destroy_Seqstack(s)销毁栈

}

栈的链式存储

栈也可以用链式存储方式实现,一般链栈用单链表表示,其节点结构与单链表的结构相同。

例2、表达式求值

表达式求值一般形式中缀表示,后缀表示,前缀表示

中缀表示<操作数><操作符><操作数>

后缀表示<操作数><操作数><操作符>

前缀表示<操作符><操作数><操作数>

1+2*(8+5)-4/2

1285-*+42/-

算法思路:

只使用一个操作数栈,当从左向右扫描表达式时,每遇到一个操作数就送入栈中保存,每遇到一个运算符就从栈中取出两个操作数进行当前的计算,然后再将结果入栈,直到整个表达式结束,这时栈顶的值就是结果。

小练:

23+((12*3-2)/4+34*5/7)+108/9

思路:

先将所有计算顺序都按计算规则用嵌套括号的形式表示出来,然后将每对括号中的运算符移到相应括号的后面,再删去所有的括号。

队列

一、队列的定义

队列(Queue)是运算受到限制的一种线性表。

只允许在表的一端进行插入,而在另一端进行删除元素的线性表。

队尾(rear)是允许插入的一端。

队头(front)是允许删除的一端。

空队列是不含元素的空表。

假设有个队列Q=(a1,a2,…,an),如图所示,则a1为队头元素,an为队尾元素。

元素入队的次序为a1,a2,…,an,而出队的次序为a1,a2,…,an。

可见队列的操作是按照先进先出的原则进行的。

队列是先进先出(FirstInFirstOut,简称FIFO结构)或后进后出(LastInLastOut)的线性表,简称LILO结构。

二、队列的基本操作

Init_Queue(q)。

初始化队列q,即置q为空队列。

Empty_Queue(q)。

判定q是否为空。

若q为空,则返回值为1,否则返回值为0。

Destroy_Queue(q).销毁队列

In_Queue(q)。

入队列操作

Out_Queue(q)。

出队操作

三、队列的顺序存储表示与实现

与栈一样,队列的顺序表示是用一组地址连续的存储空间存放队列中的元素,并设置两个分别指示队头元素的存储位置和队尾元素的存储位置的变量front,rear

顺序队列的类型定义如下:

#defineQueueSIZE100;

typedefstruct{

QElemType*base;

intfront;

intrear;

}SqQueue;

其中base为连续空间首地址,front为队首,rear为队尾。

队列的插入删除操作如下图所示:

从图中可以看出,在队列刚建立时,需要首先对它进行初始化,令front=rear=0。

每当加入一个新元素时,在rear的位置上插入新元素,然后让队尾指针加1。

因而指针rear指示了队尾元素的后面一个位置。

而对头指针front则不然,它指示的是真正队头元素所在的位置。

所以,如果要退出队头元素时,先将front所指位置上的元素返回,然后让队头元素指针front加1。

从图中还可以看出,如果队头指针front==rear,队列为空,而当rear==QueueSize时,队列为满,如果再加入新元素,就会产生"溢出"。

但是这种"溢出"并不是真正的溢出,在数组的前端还可能有空位置,所以这是一种假溢出。

为了能够充分的使用数组中的存储空间,把数组的前端和后端连接起来,形成一个环形的表,即把存储队列元素的表从逻辑上看成一个环,成为循环队列(CircularQueue)。

如下图所示,循环队列的首尾相接,当队头指针front和队尾指针rear

当front==rear为空队列(a)

(b)区分空队列和满队列,少用一个元素空间,即Q->front所指位置不用,使队尾指针Q->rear永远赶不上Q->fron,当队尾指针加1从后面赶上队头指针就表示队满。

四、队列应用举例

栈和队列的共同点是()

A都是先进先出B都是先进后出

C只允许在端点处插入和删除元素D没有共同点

在顺序循环队列中,队尾指针指向队尾元素的()位置

A前一个B后一个C当前D以上都不对

若用一个大小为6的数组来实现循环队列,且当前rear和front的值分别为0和3,当从队列中删除一个元素,再加上两个元素后,rear和front的值分别为()

A1和5B2和4C4和2D5和1

舞伴问题

1、问题叙述

 假设在周末舞会上,男士们和女士们进入舞厅时,各自排成一队。

跳舞开始时,依次从男队和女队的队头上各出一人配成舞伴。

若两队初始人数不相同,则较长的那一队中未配对者等待下一轮舞曲。

现要求写一算法模拟上述舞伴配对问题。

2、问题分析

 先入队的男士或女士亦先出队配成舞伴。

因此该问题具体有典型的先进先出特性,可用队列作为算法的数据结构。

 在算法中,假设男士和女士的记录存放在一个数组中作为输入,然后依次扫描该数组的各元素,并根据性别来决定是进入男队还是女队。

当这两个队列构造完成之后,依次将两队当前的队头元素出队来配成舞伴,直至某队列变空为止。

此时,若某队仍有等待配对者,算法输出此队列中等待者的人数及排在队头的等待者的名字,他(或她)将是下一轮舞曲开始时第一个可获得舞伴的人。

3、具体算法及相关的类型定义

typedefstruct{

charname[20];

charsex;//性别,'F'表示女性,'M'表示男性

}Person;

typedefPersonDataType;//将队列中元素的数据类型改为Person

voidDancePartner(Persondancer[],intnum)

{//结构数组dancer中存放跳舞的男女,num是跳舞的人数。

inti;

Personp;

CirQueueMdancers,Fdancers;

Init_Queue(&Mdancers);//男士队列初始化

Init_Queue(&Fdancers);//女士队列初始化

for(i=0;i

p=dancer[i];

if(p.sex=='F')

In_Queue(&Fdancers.p);//排入女队

else

In_Queue(&Mdancers.p);//排入男队

}

printf("Thedancingpartnersare:

\n\n");

while(!

QueueEmpty(&Fdancers)&&!

QueueEmpty(&Mdancers)){

//依次输入男女舞伴名

p=Out_Queue(&Fdancers);//女士出队

printf("%s",p.name);//打印出队女士名

p=Out_Queue(&Mdancers);//男士出队

printf("%s\n",p.name);//打印出队男士名

}

if(!

QueueEmpty(&Fdancers)){//输出女士剩余人数及队头女士的名字

printf("\nThereare%dwomenwaitinforthenextround.\n",Fdancers.count);

p=QueueFront(&Fdancers);//取队头

printf("%swillbethefirsttogetapartner.\n",p.name);

}else

if(!

QueueEmpty(&Mdancers)){//输出男队剩余人数及队头者名字

printf("\nThereare%dmenwaitingforthenextround.\n",Mdacers.count);

p=QueueFront(&Mdancers);

printf("%swillbethefirsttogetapartner.\n",p.name);

}

}//DancerPartners

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

当前位置:首页 > 解决方案

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

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