堆栈与队列.ppt
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Rr_Ls (Ls_top) {
scanf ("%c", &x) ; while (x !='\n') /* 进栈 */ {
Push_Ls(Ls_top, x) ; scanf ("%c", &x); } while (Ls_top != NULL) 顶元素出栈,输出 */ { Pop_Ls (Ls_top, x) ; pirntf ("%c", x) ; } }
创建一个顺序栈Ss,算法名为Create_Ss(),
参数为Ss、Ss_top、Ss_max。
Create_Ss (Ss, Ss_top, Ss_max)
{
elemtype Ss[MAX*size]; 连续的存储区 */
/*通过数组,申请一个
Ss_max = MAX ; 个数设置为MAX */
/* 将顺序栈可容纳的最多元素
(A) 一定是2
(B) 一定是1
(C) 不可能是1
(D) 以上都不对
答:当p1=3时,说明1,2,3先进栈,立即出栈3,然后可能 出栈,即为2,也可能4或后面的元素进栈,再出栈。因此,p2可 能是2,也可能是4,…,n,但一定不能是1。所以本题答案为C。
例3-5 设有6个元素a1、a2、a3、a4、 a5、a6,它们以此顺序依次进栈(即a1必须 最先进栈,然后是a2进栈,最后才是a6进 栈)。假定要求它们的出栈顺序是a2、a3、 a4、a6、a5、a1,那么应该如何安排push和 pop操作序列?这个栈的容量至少要有多大?
Pop_Ls (Ls_top, x)
{
if (Ls_top == NULL) */
/* 链栈已空,不能再出栈
printf ("The linked stack is underflow!");
else
/* 实现出栈 */
{
①ptr = Ls_top ; 顶结点 */
/* 让指针ptr指向栈
②x = ptr->Data ;
3.1.3 堆栈的链式存储实现
当采用链式存储结构实现一个堆栈时, 就称它为“链栈”。由于堆栈是线性表的一 个特例,因此,链栈就是链表的一个特例。 通常,链栈都是以单链表结构的形式来表示 的。
图3-6 链栈的示意图
1.创建一个链栈
算法3-6 创建一个空链栈。 创建一个空链栈Ls,算法名为
Create_Ls(),参数为Ls_top。 Create_Ls (Ls_top) {
3.1 堆 栈 3.1.1 堆栈的基本知识
若对线性表加以限定,使得插入和删除操作只能在 它的某一端进行,那么这种线性表就被称为“堆 栈”,简称为“栈”。所以,栈是一种特殊的线性 表。 由此定义可知: •栈是一个线性表,栈中数据元素间的逻辑结构呈线 性关系. •对栈的插入操作,被限制在表的一端进行;对栈的 删除操作,同样被限制在表的这一端进行,不能任意 为之.
Ss_top = 0 ;
/* 设置栈顶指针,开始时为空 */
return Ok;
}
图3-2 创建后的空顺序栈示意图
用c语言的数组来实现顺序栈。如果是那样, 由于c语言的数组下标规定是从0开始的, 那么最初应该把Ss_top设置程成-1,变化 范围从0到Ss_max-1。
2.往顺序栈里插入一个新元素——进栈
答:所有可能的出栈次序如下: abcd abdc acbd acdb adcb bacd badc bcad bcda bdca cbad cbda cdba dcba
例3.2 设一个栈的输入序列为A,B,C,D,则借助 一个栈所得到的输出序列不可能是 。
(A) A,B,C,D (B) D,C,B,A
3.删除顺序栈的栈顶元素——出栈
算法3-3 顺序栈的出栈算法。 根据Ss_top的指示,将当前栈顶元素的 内容取出送入变量x,然后将其从栈中删除。 算法名为Pop_Ss (),参数为Ss、x。
Pop_Ss (Ss_top, x)
{
if (Ss_top == 0 )
/* 顺序栈为空 */
printf ("The stack is empty !");
else x = Ss[Ss_top] ;
}
5.对顺序栈进行遍历
算法3-5 遍历顺序栈算法。 已知顺序栈Ss,把它栈顶到栈底诸元素 的值逐个显示出来。算法名为Display_Ss(), 参数为Ss、Ss_top。
Display_Ss(Ss, Ss_top) {
i = Ss_top ; for ( i;i>=0; i--)
3.1.2 堆栈的顺序存储实现
当采用顺序式存储结构实现一个堆栈时, 就称它为“顺序栈”。由于堆栈是线性表的 一个特例,因此,顺序栈就是顺序表的一个 特例。
1.创建一个顺序栈
算法3-1 新建顺序栈的算法。
为了创建一个顺序栈Ss,除了需要通过数组 向系统申请一个连续的存储区、给出数组(也就是 顺序栈)的最大容量Ss_max之外,还需要设置一 个元素个数计数器Ss_top,初始时它为0。随着元 素的进、出栈,用Ss_top记数,从1变化到Ss_max, 因此它实际上就是数组的下标。为了方便,我们把 Ss_top成为栈顶元素指针,简称为栈顶指针。
每一个顺序栈在运作过程中,其栈顶位置是变化的,栈 底是不变的。基于这种特点,在程序设计中,可以让两 个顺序栈“共享”一个连续的存储区,互补存储空间的 不足,以达到减少发生“上溢”出错、节约存储空间的 目的。 下图中,只有当Ss_top1和Ss_top2都指向区域中同一个位 置时,才会发生上溢”出错
printf ("%d", Ss[i]); }
注意,操作“i = Ss_top ”是非常必要的,我们不能把它 去掉。因为若把算法变为:
Display_Ss(Ss, Ss_top) { for (Ss_top ; Ss_top >=0; Ss_top --)
printf ("%d", Ss[Ss_top]); } 那么算法执行完毕后, Ss_top就指向顺序栈的栈底了, 再用它就找不到原先的栈顶元素了。 为了确保Ss_top总是指向栈顶元素,又能够把栈中所有 的元素都显示出来,就必须用另一个变量(这里就是i) 来代替Ss_top进行变化。
由于顺序栈事先确定了所占用存储区的大 小,所以对它的进栈操作要注意上溢发生的 可能性.但对于链栈而言,是动态申请存储结 点,然后进行插入,所以根本不用考虑发生上 溢的问题,这时链栈的一大优点.
3.从链栈里删除一个元素——出栈
算法3-8 链栈出栈算法。 已知链栈Ls。根据Ls_top的指示,将栈 顶元素取值存入变量x,然后删除。算法名 为Pop_Ls (),参数为Ls_top、x。
图3-4 共享存储空间的两个顺序栈
采用这样的技术组织顺序栈时,有两点要
注意,一是两个顺序栈中数据元素的类型
和尺寸大小应该完全一样:二是一个元素 打算进入顺序栈Ss1或进入顺序栈Ss2,对 指针进入顺序栈Ss1_top1和Ss2_top2做的 操作是不一样的,即对顺序栈Ss1的 Ss1_top1应该做“++”操作(朝大方向 变化),对顺序栈Ss2的Ss2_top1应该做 “--”操作(朝小方向变化)。
③Ls_top = ptr->Next ;
④free (ptr) ;
}
}
图3-8 一个元素从链栈中出栈的示意图
例3-3 编写一个算法,利用堆栈结构 将键盘上输入的字符串逆向输出,整个输入 在遇到回车换行符(‘\n’)时停止。
解:由于并不知道输入的字符串到底有 多长,因此采用链栈来解决这个问题比较合 适。在给出的算法里,我们直接调用了上面 给出的算法3-7和算法3-8。
(A) i
(B) n-i
(C) n-i+1
(D) 不确定
答:当p1=n时,输出序列必是n,n-1,…,3,2,1,则有:
p2=n-1,
p3=n-2,
…,
pn=1
推断出pi=n-i+1,所以本题答案为C。
例3.4 设n个元素进栈序列是1,2,3,…,n,其输出序列 是p1,p2,…,pn,若p1=3,则p2的值 。
第3章 堆栈与队列
3.1 堆
栈
3.2 队
列
3.3 栈 与 队 列 的 实 际 应 用
堆栈和队列是两种特殊的线性表,是对 线性表施行的操作加以一定限制后得到的数 据结构。堆栈和队列在程序设计中是极为有 用的一种重要工具。
本章主要介绍以下几个方面的内容:
堆栈的基本知识和存储实现; 队列的基本知识和存储实现; 堆栈和队列的具体应用举例。
else
{
x = Ss[Ss_top] ;
Ss_top -- ;}
}
注意:由于Ss_top总是指向当前栈中栈顶元素的位置,所 以应将所指位置里的内容读出送入变量x,这样以后,在调 整Ss_top的指向,达到指向新的栈顶元素位置的目的。
图3-5 元素进、出栈时Ss_top的变化
由于是出栈操作,因此必须要注意的边界 问题是栈是否为空。算法中是通过检查条 件: Ss_top == 0是否成立来判断的。 如果在顺序栈空时仍打算出栈,就称为发 生了“下溢(Underflow)”出错。
return ERROR ;
else
{
Ss_top++;
/* 调整栈顶指针 */
Ss [Ss_top] = x;
/* x进栈 */
}
}
图3-3 Ss_top与进栈元素间的关系
Hale Waihona Puke Baidu
由于顺序栈占用的存储空间是一定的,因 此在实施进栈操作时必须要注意的边界问 题是该栈是否已满。算法中通过检查条件: Ss_top == Ss_max是否成立来做出判断。 如果在顺序栈满时仍打算进栈,就称为发 生了“上溢(Overflow)”出错。
在一个栈中,允许进行插入和删除的那一端
被称为“栈顶”,不能进行插入和删除的那一端被 称为“栈底”。从当前栈顶处插入一个新元素的操 作,称为“进栈(push)”,插入的这个元素成为了 新的栈顶;从当前栈顶处删除一个元素的操作,称 为“出栈(pop)”,这时栈中被删除元素的下一个 元素成为新的栈顶。可见,在栈的运作过程中,随着 数据元素的进栈、出栈,栈顶元素是不断变化的。
当一个栈里不含有任何数据元素时,称 其为“空栈”,对于一个空栈,因为它已经 没有元素了,所以不能在对它进行出栈操作 了。
常把栈称作是有“后进先出(LIFO)”、 或有“先进后出(FILO)”逻辑特点的数据 结构,其意是元素到达栈的顺序与元素离开 栈的顺序恰好是相反的。
图3-1 栈的示意图
例3.1 设有4个元素a、b、c、d进栈,给出它们 所有可能的出栈次序。
(C) A,C,D,B (D) D,A,B,C
答:可以简单地推算,得容易得出D,A,B,C是 不可能的,因为D先出来,说明A,B,C,D均在栈中,按 照入栈顺序,在栈中顺序应为D,C,B,A,出栈的顺序 只能是D,C,B,A。所以本题答案为D。
例3.3 已知一个栈的进栈序列是1,2,3,…,n,其输出序列 是p1,p2,…,pn,若p1=n,则pi的值 _ 。
Push_Ls(Ls_top, x) {
ptr = malloc (size) ; ①ptr->Data = x ; ②ptr->Next = Ls_top ; 结点插入 */ ③Ls_top = ptr ; }
/* 申请一个存储结点 */ /* 调整链表指针,完成
图3-7 一个元素进入链栈的示意图
算法3-2 顺序栈的进栈算法。 根据Ss_top的指示,让数据元素x进入 顺序栈Ss的栈顶,成为新的栈顶元素。算法 名为Push_Ss (),参数为Ss、Ss_top、 Ss_max、x。
Push_Ss(Ss, Ss_top, Ss_max, x)
{
if (Ss_top == Ss_max)
/* 顺序栈已满 */
Ls_top = NULL ; }
链栈是进栈和出栈操作都被限制在表首进 行的单链表,因此与单链表不同,链栈不需要 设表头结点,而是在创建时只要将Ls_top设 置为NULL.
2.往链栈里插入一个新元素——进栈
算法3-7 链栈进栈算法。 已知链栈Ls。根据Ls_top的指示,让数 据元素x进入链栈Ls的栈顶位置,成为新的 栈顶元素。算法名为Push_Ls (),参数为 Ls_top、x。
4.获取顺序栈栈顶元素
算法3-4 获取顺序栈栈顶元素的算法。 有顺序栈Ss,将当前栈顶元素值读到变量x。 算法名为Get_Ss(),参数为Ss、Ss_top、x。
Get_Ss(Ss, Ss_top, x) {
if (Ss_top == 0) printf ("The stack is empty !");