上大数据结构课件第4章 栈和队列
合集下载
数据结构-栈和队列PPT课件
初始条件:栈 S 已存在且非空。 操作结果:删除 S 的栈顶元素,并用 e 返回其值。
.
15
栈的抽象数据类型定义
StackTraverse(S, visit( )) 初始条件:栈 S 已存在且非空,visit( )为元素的访问
函数。 操作结果:从栈底到栈顶依次对S的每个元素调用函数
visit( ),一旦visit( )失败,则操作失败。 } ADT Stack
.
29
3.1.2.2 栈的静态顺序存储表示
4 弹栈(元素出栈)
Status pop( SqStack S, ElemType *e ) /*弹出栈顶元素*/ { if ( S.top==0 ) return ERROR ; /* 栈空,返回错误标志 */ *e=S.stack_array[S.top] ; S.top-- ; return OK ; }
.
11
3.1.1 栈的基本概念
2 栈的抽象数据类型定义
ADT Stack{ 数据对象:D ={ ai|ai∈ElemSet, i=1,2,…,n,n≥0 } 数据关系:R ={<ai-1, ai>|ai-1,ai∈D, i=2,3,…,n } 基本操作:初始化、进栈、出栈、取栈顶元素等
} ADT Stack
进栈(push) 出栈(pop)
top
an
⋯⋯
ai ⋯⋯
a2
bottom
a1
图3-1 顺序栈示意图
.
6
栈的示意图
入栈
• 特点
• 先进后出(FILO) 出栈 • 后进先出(LIFO)
栈顶 栈顶 栈顶
a3 a2
插入:入栈、进栈、压栈 删除:出栈、弹栈
.
15
栈的抽象数据类型定义
StackTraverse(S, visit( )) 初始条件:栈 S 已存在且非空,visit( )为元素的访问
函数。 操作结果:从栈底到栈顶依次对S的每个元素调用函数
visit( ),一旦visit( )失败,则操作失败。 } ADT Stack
.
29
3.1.2.2 栈的静态顺序存储表示
4 弹栈(元素出栈)
Status pop( SqStack S, ElemType *e ) /*弹出栈顶元素*/ { if ( S.top==0 ) return ERROR ; /* 栈空,返回错误标志 */ *e=S.stack_array[S.top] ; S.top-- ; return OK ; }
.
11
3.1.1 栈的基本概念
2 栈的抽象数据类型定义
ADT Stack{ 数据对象:D ={ ai|ai∈ElemSet, i=1,2,…,n,n≥0 } 数据关系:R ={<ai-1, ai>|ai-1,ai∈D, i=2,3,…,n } 基本操作:初始化、进栈、出栈、取栈顶元素等
} ADT Stack
进栈(push) 出栈(pop)
top
an
⋯⋯
ai ⋯⋯
a2
bottom
a1
图3-1 顺序栈示意图
.
6
栈的示意图
入栈
• 特点
• 先进后出(FILO) 出栈 • 后进先出(LIFO)
栈顶 栈顶 栈顶
a3 a2
插入:入栈、进栈、压栈 删除:出栈、弹栈
《栈和队列》课件
栈与队列的区别
数据存储方式
栈是后进先出(Last In First Out, LIFO)的数据结构,新元素总是被添加到栈顶,移除 元素时也是从栈顶开始。而队列是先进先出(First In First Out, FIFO)的数据结构,新 元素被添加到队列的尾部,移除元素时从队列的头部开始。
操作方式
栈的主要操作有push(添加元素)和pop(移除元素),而队列的主要操作有enqueue (添加元素)和dequeue(移除元素)。
《栈和队列》ppt课件
目录
CONTENTS
• 栈的定义与特性 • 队列的定义与特性 • 栈与队列的区别与联系 • 栈和队列的实现方式 • 栈和队列的算法实现 • 总结与思考
01 栈的定义与特性
CHAPTER
栈的定义
栈是一种特殊的线性 数据结构,遵循后进 先出(LIFO)原则。
栈中的元素按照后进 先出的顺序排列,最 新加入的元素总是位 于栈顶。
02
如何实现一个队列,并 实现其基本操作( enqueue、dequeue、 front)?
03
栈和队列在应用上有哪 些区别?请举例说明。
04
请设计一个算法,使用 栈实现括号匹配的功能 ,并给出测试用例。
谢谢
THANKS
。
队列的应用场景
任务调度
在任务调度中,可以将任 务按照优先级放入队列中 ,按照先进先出的原则进 行调度。
网络通信
在网络通信中,可以将数 据包放入队列中,按照先 进先出的原则进行发送和 接收。
事件处理
在事件处理中,可以将事 件放入队列中,按照先进 先出的原则进行处理。
03 栈与队列的区别与联系
CHAPTER
应用场景
栈和队列PPT课件
p=Q.front->next;
e=p->data;
Q.front->next=p->next;
if(Q.rear==p) Q.rear=Q.front;
free(p);
return OK;
}
经营者提供商品或者服务有欺诈行为 的,应 当按照 消费者 的要求 增加赔 偿其受 到的损 失,增 加赔偿 的金额 为消费 者购买 商品的 价款或 接受服 务的费 用
typedef struct
{ Selemtype *base; //在栈构造之前和销毁之后,base的值为NULL
Selemtype *top; //栈顶指针
int
stacksize; //当前已分配的存储空间,以元素为单位
} sqstack;
栈的基本操作:P46
经营者提供商品或者服务有欺诈行为 的,应 当按照 消费者 的要求 增加赔 偿其受 到的损 失,增 加赔偿 的金额 为消费 者购买 商品的 价款或 接受服 务的费 用
x
x
y^ rear
y^ rear
经营者提供商品或者服务有欺诈行为 的,应 当按照 消费者 的要求 增加赔 偿其受 到的损 失,增 加赔偿 的金额 为消费 者购买 商品的 价款或 接受服 务的费 用
❖构造空队列
status InitQueue(LinkQueue &Q) {
Q.front=Q.rear=(QueuePtr)malloc(sizeof(Qnode));
若表达式未输入完,转1
例 计算 4+3*5
后缀表达式:435*+
top 3
top 4
4
top 5 3
7
top top
栈与队列ppt课件
栈
栈(stack)又称堆栈,它是运算受限的线性表,其限 制是仅允许在表的一端进行插入 和删除操作,不允许
在其他任何位置进行插入、查找、删除等操作。表中进 行插入、删除操 作的一端称为栈顶(top),栈顶保存 的元素称为栈顶元素。相对的,表的另一端称为栈底 (bottom)。 当栈中没有数据元素时称为空栈;向一 个栈插入元素又称为进栈或入栈;从一个栈中删除元素
下面以图 4-3 所示的表示方法来说明这个问题。在图 4-3 中用队首指针 front指向队首元素所在的单元,用队尾指针rear指向队尾元素所在单元的 后一个单元。如此在图 4-4(b)中 所示循环队列中,队首元素为e0,队 尾元素为e3。当e4、e5、e6、e7相继进入队列后,如图 4-4(c)所示, 队列空间被占满,此时队尾指针追上队首指针,有rear = front。反之,如 果从图4-4(b)所示的状态开始,e0、e1、e2、e3相继出队,则得到空 队列,如图 4-4(a)所示,此 时队首指针追上队尾指针,所以也有front = rear。可见仅凭front与rear是否相等无法判断队列的状态是“空”还是 “满”。解决这个问题可以有两种处理方法:一种方法是少使用一个 存储 空间,当队尾指针的下一个单元就是队首指针所指单元时,则停止入队。 这样队尾指针 就不会追上队首指针,所以在队列满时就不会有front = rear。 这样一来,队列满的条件就变 为(rear+1)% capacity = front,而队列判空 的条件不变,仍然为front = rear。另外一种解决这 个问题的方法是增设一 个标志,以区别队列是“空”还是“满”,例如增设size变量表明队 列中 数据元素的个数,如果size = Max则队列满。
第四章栈与队列
OPTR
# # #,* #,*,( #,*,( #,*,(,- #,*,(,- #,*,( #,* #
OPND
3 3 3 3,7 3,7 3,7,2 3,5 3,5 15
INPUT
3*(7-2)# *(7-2)# (7-2)# 7-2)# -2)# 2)# )# )# # #
OPERATE
Push(opnd,’3’) Push(optr,’*’) Push(optr,’(’) Push(opnd,’7’) Push(optr,’-’) Push(opnd,’2’) Operate(7-2)
}
建立空链栈:
struct stacknode *top=NULL; //初始化空栈,不带头结点
从空栈始,依次调用进栈算法建立含有若干个元素的 非空栈。
4.2 栈的应用举例
栈结构具有的后进先出特性,致使栈成为程序 设计中常用的工具。 一、栈的应用举例-----数制转换
十进制N和其它进制数的转换是计算机实现计 算的基本问题,其解决方法很多,其中一个简单算 法基于下列原理:
栈1底
栈1顶
栈2顶
图 两 个 栈 共 享 存 储 单 元 示 意 图
栈2底
三 链栈
栈的链式存储结构称为链栈,是插入和删 除操作仅限制在表头位置上进行的单链。由 于只能在链表头部进行操作,栈顶指针就是
链表的头指针。链栈的结点定义:
typedef struct stacknode
{ ElemType data; …… struct node *next;
现。特别注意栈空和栈满的条件; 3、熟练掌握队列的顺序表示、链表表示以及相应操作的实
现。特别是循环队列中队头与队尾指针的变化情况。
[理学]第4章 栈和队列ppt课件
10
例3:一个栈的输入序列是12345,假设在入栈的 过程中允许出栈,那么栈的输出序列43512能够 实现吗?12345的输出呢?
答: 43512不能够实现,主要是其中的12顺序不能实 现; 12345的输出可以实现,每压入一数便立刻弹出 即可。
11
例4:
计算机系2001年考研题
设依次进入一个栈的元素序列为c,a,b,d, 那么可得到出栈的元素序列是:
操作数可以是常数也可以是被阐明为变量或 常量的标识符; 运算符可以分为算术运算符、关系运算符和 逻辑运算符等三类; 根本界限符有左右括弧和表达式终了符等。
16
4.5 算术表达式的计算
算术运算的规那么是:先乘除后加减、先左后
右和先括弧内后括弧外。表达式:3+4
对表达式进展运算不能按前其缀中:运+算3符4出现的先
29
循环队列的顺序存储
1、初始化队列 void InitQueue(Queue &q) {
q.MaxSize=10; q.queue=new ElemType[q.MaxSize]; q.front=q.rear=0; }
30
入队时空间不够的处置
90
30 40 50 60 70 80
90 30 40 50 60 70 80 30 40 50 60 70 80 90
9
输出sum= x4+x3 +x2+x1
输出 sum= x4+x3 +x2
输出 输出 sum= sum=
x4+x3 0+x4
程序功能:对键盘输入数 据求和,直到输入0终了
输出 sum=0
例2 一个栈的输入序列为1,2,3,假设在入栈的过程 中允许出栈,那么能够得到的出栈序列是什么?
例3:一个栈的输入序列是12345,假设在入栈的 过程中允许出栈,那么栈的输出序列43512能够 实现吗?12345的输出呢?
答: 43512不能够实现,主要是其中的12顺序不能实 现; 12345的输出可以实现,每压入一数便立刻弹出 即可。
11
例4:
计算机系2001年考研题
设依次进入一个栈的元素序列为c,a,b,d, 那么可得到出栈的元素序列是:
操作数可以是常数也可以是被阐明为变量或 常量的标识符; 运算符可以分为算术运算符、关系运算符和 逻辑运算符等三类; 根本界限符有左右括弧和表达式终了符等。
16
4.5 算术表达式的计算
算术运算的规那么是:先乘除后加减、先左后
右和先括弧内后括弧外。表达式:3+4
对表达式进展运算不能按前其缀中:运+算3符4出现的先
29
循环队列的顺序存储
1、初始化队列 void InitQueue(Queue &q) {
q.MaxSize=10; q.queue=new ElemType[q.MaxSize]; q.front=q.rear=0; }
30
入队时空间不够的处置
90
30 40 50 60 70 80
90 30 40 50 60 70 80 30 40 50 60 70 80 90
9
输出sum= x4+x3 +x2+x1
输出 sum= x4+x3 +x2
输出 输出 sum= sum=
x4+x3 0+x4
程序功能:对键盘输入数 据求和,直到输入0终了
输出 sum=0
例2 一个栈的输入序列为1,2,3,假设在入栈的过程 中允许出栈,那么能够得到的出栈序列是什么?
第4章栈及队列
}
4.1.5 栈的链式存储结构——链栈 1.链栈结构及数据类型
它是一种限制运算的链表,即规定链表中的扦入和删 除运算只能在链表开头进行。链栈结构见下图。
top 头
an
an-1
……
栈顶
图 3-5 链栈结构示意图
a1 ^
栈底
单链表的数据结构定义为: typedef struct node
{ elemtype data; //数据域 struct node *next; //指针域
3.出栈: POP(&S) 删除栈S中的栈顶元素,也称为”退栈”、 “删除”、 “弹出”。
4.取栈顶元素: GETTOP(S) 取栈S中栈顶元素。 5.判栈空: EMPTY(S) 判断栈S是否为空,若为空,返回值为1,否则返回值为0。
4.1.3 栈的抽象数据类型描述
ADT Stack {
Data: 含有n个元素a1,a2,a4,…,an,按LIFO规则存放,每个元素的类型都为 elemtype。 Operation: Void inistack(&s) //将栈S置为一个空栈(不含任何元素) Void Push(&s,x) //将元素X插入到栈S中,也称为 “入栈”、 “插 入”、 “压入”
{s->top[0]=-1; s->top[1]=m; }
(2)两个栈共享存储单元的进栈算法 int push(duseqstack *s, elemtype x, int i) //将元素x进入到以S为栈空间的第i个栈中 { if (s->top[0] ==s->top[1]-1) { printf(“overflow”); return (0);} if (i!=0 || i!=1) {printf(“栈参数出错“);return (0);} if(i= =0) //对0号栈进行操作 { s->top[0]++;s->stack[s->top[0]]=x;} else {s->top[1]--; s->stack[s->top[1]]=x;} return (1); }}
4.1.5 栈的链式存储结构——链栈 1.链栈结构及数据类型
它是一种限制运算的链表,即规定链表中的扦入和删 除运算只能在链表开头进行。链栈结构见下图。
top 头
an
an-1
……
栈顶
图 3-5 链栈结构示意图
a1 ^
栈底
单链表的数据结构定义为: typedef struct node
{ elemtype data; //数据域 struct node *next; //指针域
3.出栈: POP(&S) 删除栈S中的栈顶元素,也称为”退栈”、 “删除”、 “弹出”。
4.取栈顶元素: GETTOP(S) 取栈S中栈顶元素。 5.判栈空: EMPTY(S) 判断栈S是否为空,若为空,返回值为1,否则返回值为0。
4.1.3 栈的抽象数据类型描述
ADT Stack {
Data: 含有n个元素a1,a2,a4,…,an,按LIFO规则存放,每个元素的类型都为 elemtype。 Operation: Void inistack(&s) //将栈S置为一个空栈(不含任何元素) Void Push(&s,x) //将元素X插入到栈S中,也称为 “入栈”、 “插 入”、 “压入”
{s->top[0]=-1; s->top[1]=m; }
(2)两个栈共享存储单元的进栈算法 int push(duseqstack *s, elemtype x, int i) //将元素x进入到以S为栈空间的第i个栈中 { if (s->top[0] ==s->top[1]-1) { printf(“overflow”); return (0);} if (i!=0 || i!=1) {printf(“栈参数出错“);return (0);} if(i= =0) //对0号栈进行操作 { s->top[0]++;s->stack[s->top[0]]=x;} else {s->top[1]--; s->stack[s->top[1]]=x;} return (1); }}
第4章-栈与队列PPT课件
.
34
其算法框架如下:
mazeFrame( void ) {
创建一个(保存探索过程的)空栈;
把入口位置压入栈中;
while 栈不空时{
取栈顶位置并设置为的当前位置;
while 当前位置存在试探可能{
取下一个试探位置;
if (下一个位置是出口)
打印栈中保存的探索过程然后返回
if(下一个位置是通道)
把当前位置进栈并且设置为的当前位置;
n = n – 1; } res = 1; while (! isEmptyStack_seq(st)) { res = res * top_seq(st);
pop_seq(st); } free(st);
return ( res );
}
.
31
4.3.2 迷宫问题
迷宫问题要求的就是:从入口到出口的一 个以空白方块构成的(无环)路径。
.
28
当被调函数运行结束,需要返回到调用函数时,一 般的返回处理也可以分解成下列三步: (1) 传送返回信息。 (2) 释放被调函数的数据区。 (3) 把控制按返回地址转移到调用函数中去。
.
29
内存空间的分配:静态分配和动态分配。 要完成递归算法转换为非递归算法,需要在内
存中开辟一个存储区域称为运行栈(或简称栈)。 每次调用时,将动态区指针下推,分配被调函数
.
25
在fact(3)的计算过程中,我们实际不需 要生成3个相同的fact程序,只要一个程序 在不同的阶段能够处理(3份)不同数据。根 据后进先出的原则,只要保证把最后调用 的程序使用的空间,保存在一个栈的栈顶 就可以了。
.
26
递归函数到非递归函数的转换
《栈和队列》课件
栈和队列的本质思想是
实现方式的重要性
通过限制插入和删除的
理解栈和队列的概念以
方式,实现了数据的有
及它们不同的实现方式
序存储和操作。
对于和队列在算法和
数据结构中的广泛 应用
栈和队列作为基本的数
据结构,在算法和数据
结构的设计中有着广泛
的应用。
1 Enqueue
插入元素到队列尾部。
2 Dequeue
从队列头部删除元素。
3 Front
获取队列头部元素的值,不改变队列的状 态。
4 isEmpty
判断队列是否为空。
队列的应用
约瑟夫问题
通过模拟元素出队/入队的 过程,解决经典的约瑟夫 问题。
循环队列
使用数组实现的循环队列, 可以有效地利用存储空间。
1 Push
将元素压入栈顶。
3 Peek
获取栈顶元素的值,不改变栈的状态。
2 Pop
将栈顶元素弹出。
4 isEmpty
判断栈是否为空。
栈的应用
中缀表达式转后缀表 达式
利用栈的特性将中缀表达 式转换为后缀表达式,方 便计算机进行计算。
括号匹配问题
利用栈判断一个表达式中 的括号是否匹配。
计算器程序
使用栈来实现简单的计算 器,可以进行基本的加减 乘除运算。
队列与广度优先搜索
在图的遍历过程中,广度 优先搜索需要使用队列来 保存未访问的节点。
栈和队列的比较
1 栈和队列的异同
栈和队列都是线性表,但栈是后进先出,队列是先进先出。
2 栈和队列的不同应用场景
栈在表达式求值和程序调用等领域有广泛应用,而队列在调度和模拟等领域有广泛应用。
总结
《数据结构堆栈》PPT课件
4.2堆栈的顺序存储结构
0 1 2 ……
a1 a2 … ai
top1
top1
什么时候栈1为空?
S-1
bj … … b2 b1
top2 top1= -1
4.2堆栈的顺序存储结构
0 1 2 ……
a1 a2 … ai
top1 什么时候栈1为空? 什么时候栈2为空?
S-1
bj … … b2 b1
top2
操作接口: 入栈:p75 出栈:p75
4.3堆栈的链式存储结构
顺序栈和链栈的比较
• 时间性能:相同,都是常数时间O(1)。 • 空间性能:
– 顺序栈:有元素个数的限制和空间浪费的问题。 – 链栈:没有栈满的问题,只有当内存没有可用空间
时才会出现栈满,但是每个元素都需要一个指针域, 从而产生了结构性开销。
012 3 4 56 78
a1
top 确定用数组的哪一端表示栈底。 附设指针top指示栈顶元素在数组中的位置。
4.2堆栈的顺序存储结构
012 3 4 56 7 8
a1 a2 a3
top top top 进栈:top加1 出栈:top减1
栈空:top= -1 栈满:top= MAX_SIZE
4.2堆栈的顺序存储结构
两栈共享空间:使用一个数组来存储两个栈,让一个 栈的栈底为该数组的始端,另一个栈的栈底为该数组 的末端,两个栈从各自的端点向中间延伸。
4.2堆栈的顺序存储结构
0 1 2 ……
a1 a2 … ai
S-1
bj … … b2 b1
栈1底
top1
top2
栈2底
栈1的底固定在下标为0的一端; 栈2的底固定在下标为MaxSize-1的一端。 top1和top2分别为栈1和栈2的栈顶指针; MaxSize为整个数组空间的大小(图中用S表示);
栈及队列.ppt
二、栈的应用举例
★若读出的运算符的优先级不大于运算符栈栈顶 运算符的优先级,则从操作数栈连续推出两个操 作数,并从运算符栈推出一个运算符,然后作相 应的运算,并将运算结果压入操作数栈。在这种 情况下,当前读出的运算符下次重新考虑(即不 再读下一个符号)。
分析:表达式2+3*4-9/3;的计算过程
二、栈的应用举例
出栈时,在栈非空时,先将栈顶元素赋给指定的变 量,再将栈顶指针退一。
void pop(Stack &S, int &e) {
if(S.top==0) { cout<<"空栈";return; } e=S.data[S.top-1]; --S.top; return; }
2.栈的顺序存储及其实现
(4) 读栈顶元素:将栈顶元素赋给一个指定的变量
2 递归的实现
从递归的基本思想可以看出,计算机 执行递归过程时,需要记忆各步的状 态,以便问题的返回。这可以用栈来 实现。
a[4]={2,3,7,5} max(a,m,n) { if(m!=n)
{x=max(a,m,(m+n)/2); 2 7 y=max(a,(m+n)/2+1,n); 3 5
return x>y?x:y;} x=3 7 y=7
Struct LQueue{ node *front; node *rear;
} LQueue *LQ;
四、队列
链队的说明如下
★队头指针为LQfront,队尾指针为LQrear, 对头元素的引用为LQfrontdata,对尾元素的引用 为LQreardata. ★初始化时,设置LQfront=LQrear=NULL.
Q(1:6)
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
取栈顶元素
template<class ElemType> Status LinkStack<ElemType>::Top(ElemType &e) const { if(Empty()) // 栈空 return UNDER_FLOW; else { // 栈非空,操作成功 e = top->data;// 用e返回栈顶元素 return SUCCESS; } }
4.2.2 栈的链接存储结构
•top是栈顶指针,指向链栈的栈顶结点; •top=NULL 表示栈空; •若链栈非空,则top是指向链表的第一个结点(栈顶结点)的指针。 •栈顶结点是最后一个入栈的元素,而栈底结点是最先入栈的元素。
•链栈的结点是动态分配的,不会出现栈满的现象,只有空栈和非空栈两种状
态。
栈的基本操作
初始化:初始化一个空栈。
求长度:求栈中数据元素的数目。
取栈顶元素:当栈不空时,取栈顶数据元素,并返回成功状
态;否则返回不成功状态。 入栈:在栈顶插入一个新元素item。如果能顺利插入元素, 则返回插入成功;否则返回插入失败。
出栈:当栈不空时,删除栈顶元素,并返回出栈成功;否则
顺序栈的析构函数
template<class ElemType> SqStack<ElemType>::~SqStack() { delete []elems; }
// 释放存储空间
求顺序栈的长度
template <class ElemType> int SqStack<ElemType>::Length() const { return top; }
顺序栈的定义
// 顺序栈类
template<class ElemType> class SqStack
{Hale Waihona Puke protected: // 顺序栈的数据成员:
int top;
int maxSize;
// 栈顶指针
// 栈最大容量
ElemType *elems;// 元素存储空间
public:
SqStack(int size = DEFAULT_SIZE); virtual ~SqStack(); int Length() const; bool Empty() const;
求链式栈的长度
template <class ElemType> int LinkStack<ElemType>::Length() const { int count = 0; // 计数器 Node<ElemType> *Ptr; for (Ptr = top; Ptr != NULL; Ptr = Ptr->next) count++; } return count; }
第4章 栈 和 队 列
上海大学计算机学院 沈 俊
JShen@
主要内容
4.1 4.2 4.3 4.4 4.5 4.6 4.7 栈的基本概念 栈的存储结构 栈的基本运算 栈的简单应用举例 队列的基本概念 队列的存储结构 队列的基本运算
4.1 栈的基本概念
栈(stack)是限定仅在表尾一端进行插入或删除操作的特 殊线性表。对于栈来说, 允许进行插入或删除操作的一端称为栈 顶(top),而另一端称为栈底(bottom)。不含元素栈称为空栈, 向栈中插入一个新元素称为入栈或压栈, 从栈中删除一个元素 称为出栈或退栈。 假设有一个栈S=(a1, a2, …, an), a1先进栈, an最后进栈。称 a1为栈底元素, an为栈顶元素, 如图3.1所示。出栈时只允许在栈 顶进行, 所以an 先出栈, a1 最后出栈。因此又称栈为后进先出
遍历链式栈
template <class ElemType> void LinkStack<ElemType>::Traverse(void (*Visit)(const ElemType &)) const { Node<ElemType> *Ptr; for (Ptr = top; Ptr != NULL; Ptr = Ptr->next) (*Visit)(Ptr->data); }
遍历顺序栈
template <class ElemType> void SqStack<ElemType>::Traverse(void (*Visit)(const ElemType &)) const { for (int Pos = top-1; Pos >= 0; Pos--) (*Visit)(elems[Pos]); }
链序栈的构造函数
template<class ElemType> LinkStack<ElemType>::LinkStack() { top = NULL; }
链序栈的析构函数
template<class ElemType> LinkStack<ElemType>::~LinkStack() { Clear(); }
出栈
template<class ElemType> Status LinkStack<ElemType>::Pop(ElemType &e) { if (Empty()) // 栈空 return UNDER_FLOW; else { // 操作成功 Node<ElemType> *old_top = top;// 旧栈顶 e = old_top->data; // 用e返回栈顶元素 top = old_top->next; // top指向新栈顶 delete old_top; // 删除旧栈顶 return SUCCESS; } }
{
判断链式栈是否为空
template<class ElemType> bool SqStack<ElemType>::Empty() const { return top = = NULL; }
清空链式栈
template<class ElemType> void SqStack<ElemType>::Clear() { Node<ElemType> *Ptr; while (top != NULL) { Ptr = top; top = top->next; delete Ptr; } }
出栈
template<class ElemType> Status SqStack<ElemType>::Pop(ElemType &e) { if (Empty()) // 栈空 return UNDER_FLOW; else { // 操作成功 e = elems[--top]; return SUCCESS; } }
// 栈顶指针
public: // 链栈的函数成员: LinkStack(); virtual ~LinkStack(); int Length() const; // 求栈长度 bool Empty() const; // 判断栈是否为空 void Clear(); // 将栈清空 void Traverse(void (*Visit)(const ElemType &)) const ; Status Push(const ElemType &e); // 入栈 Status Top(ElemType &e) const; // 取栈顶元素 Status Pop(ElemType &e); // 出栈 };
取栈顶元素
template<class ElemType> Status SqStack<ElemType>::Top(ElemType &e) const { if(Empty()) // 栈空 return UNDER_FLOW; else { // 栈非空,操作成功 e = elems[top - 1]; // 用e返回栈顶元素 return SUCCESS; } }
【例4.5】 假设一个栈S为(A,B,C),采用链栈存储。
data next C data next B data next A 栈底
^
top
栈顶
(a) 栈的链接存储结构
data next E data next D data next C data next B data next A 栈底
^
top
栈顶
(b) 向链栈中插入两个结点D和E
data next D 栈顶
data next C
data next B
data next A
top
^
栈底
(c) 从链栈中删除栈顶结点E
图4.4 栈的链接存储结构及其操作过程
链式栈的类定义
#include "node.h" // 链栈类 template<class ElemType> class LinkStack { protected: // 链栈的数据成员: Node<ElemType> *top; // 结点类
判断顺序栈是否为空
template<class ElemType> bool SqStack<ElemType>::Empty() const { return top = = 0; }
清空顺序栈
template<class ElemType> void SqStack<ElemType>::Clear() { top = 0; }
返回出栈失败。 判断栈是否为空栈:如果栈为空,则返回值TRUE,否则返 回值FALSE。 清空栈:将栈为空栈。