第三章栈与队列
数据结构-Java语言描述 第三章 栈和队列

System.exit(1);
}
栈顶指针top的初始值决
top=-1;
定了后续其他方法的实现
stackArray=(T[])new Object[n];
}
【算法3-2】入栈
public void push(T obj)
{
if(top==stackArray.length-1){
T []p=(T[])new Object [top*2];
(b)元素a2入栈
an … … a2 a1
(c)元素an入栈
an-1 … a2 a1
(d)元素an出栈
a2 a1
(e)元素a3出栈
a1
(f)元素a2出栈
【例3-1】一个栈的输入序列是1、2、3、4、5,若在 入栈的过程中允许出栈,则栈的输出序列4、3、5、1、 2可能实现吗?1、2、3、4、5的输出呢?
型 正序遍历:依次访问栈中每个元素并输出
3.1.2 顺序栈
顺序栈泛型类的定义如下:
public class sequenceStack<T> {
顺序栈中一维数组 的初始长度
final int MaxSize=10;
private T[] stackArray; 存储元素的数组对象
private int top;
public void nextOrder() {
for(int i=top;i>=0;i--) System.out.println(stackArray[i]);
}
【算法3-8】清空栈操作
public void clear() {
top=-1; }
3.1.3 链栈
栈的链接存储结构称为链栈。结点类的定义,同 第二章Node类。
大学数据结构课件--第3章 栈和队列

栈满 top-base=stacksize
top
F
E
D C B
top top top top top top base
入栈PUSH(s,x):s[top++]=x; top 出栈 POP(s,x):x=s[--top]; top
base
4
A
3.1 栈
例1:一个栈的输入序列为1,2,3,若在入栈的过程中 允许出栈,则可能得到的出栈序列是什么? 答: 可以通过穷举所有可能性来求解:
3.2 栈的应用举例
二、表达式求值
“算符优先法”
一个表达式由操作数、运算符和界限符组成。 # 例如:3*(7-2*3) (1)要正确求值,首先了解算术四则运算的规则 a.从左算到右 b.先乘除后加减 c.先括号内,后括号外 所以,3*(7-2*3)=3*(7-6)=3*1=3
9
3.2 栈的应用举例
InitStack(S); while (!QueueEmpty(Q))
{DeQueue(Q,d);push(S,d);}
while (!StackEmpty(S)) {pop(S,d);EnQueue(Q,d);} }
第3章 栈和队列
教学要求:
1、掌握栈和队列的定义、特性,并能正确应用它们解决实 际问题;
用一组地址连续的存储单元依次存放从队头到队尾的元素, 设指针front和rear分别指示队头元素和队尾元素的位置。
Q.rear 5 4 Q.rear 3 2 3 2 5 4 Q.rear 3 3 5 4 5 4
F E D C
C B A
Q.front
2 1 0
C B
Q.front 2 1 0
第三章 栈和队列

栈和队列的基本操作是线性表操作的子集,是限定性(操作受限制)的数据结构。
第三章栈和队列数据结构之栈和队列23. 1 栈¾定义:是限定仅在表尾进行插入或删除操作的线性表。
(后进先出线性表LIFO)¾栈底指针(base) :是线性表的基址;¾栈顶指针(top):指向线性表最后一个元素的后面。
¾当top=base 时,为空栈。
¾基本操作:InitStack(&S), DestroyStack(&S),StackEmpty(S) , ClearStack(&S),GetTop(S ,&e), StackLength(S) ,Push(&S, e): 完成在表尾插入一个元素e.Pop(&S,&e): 完成在表尾删除一个元素。
数据结构之栈和队列3¾栈的表示和实现¾顺序栈:是利用一组地址连续的存储单元依次存放自栈底到栈顶的数据元素;栈满之后,可再追加栈空间即为动态栈。
¾顺序栈的结构类型定义:typedef int SElemType;typedef struct{SElemType *base; /* 栈底指针*/SElemType *top; /* 栈顶指针*/int stacksize; /* 栈空间大小*/ }SqStack;数据结构之栈和队列4¾基本算法描述¾建立能存放50个栈元素的空栈#define STACK_INIT_SIZE 50#define STACKINCREMENT 10Status InitStack_Sq(Stack &S){S.base=(SET*)malloc(STACK_INIT_SIZE *sizeof(SET)); /*为栈分配空间*/if(S.base==NULL)exit(OVERFLOW); /*存储分配失败*/ S.top=S.base;S.stacksize = STACK_INIT_SIZE;return OK; }数据结构之栈和队列5¾出栈操作算法void pop(Sqstack s,SElemType e){if(s.top= = s.base)return ERROR;else{s.top--;e= *s.top;}return OK;}出栈操作topABY topABYbase base数据结构之栈和队列6¾压栈操作算法void Push(SqStack s,SElemType e)if(s.top-s.base>= S.stacksize;) {S.base=(SET*)realloc(S,base,(S.stacksize+STACKINCREMEN T) *sizeof(SET)); /*为栈重新分配空间*/if(!S.base)exit(OVERFLOW);S.top=S.base+S.stacksize;S.stacksize+=STACKINCREMENT;}*S.top=e;S.top++;}return OK; }topAB压栈操作topABebase base数据结构之栈和队列7¾栈的销毁void DestroyStack_Sq(Stack &S){ if (S.base) free(S.base);S.base=NULL;S.top=NULL;S.stacksize=0;}¾栈的清除void ClearStack_Sq(Stack &S){ S.top = S.base ;}数据结构之栈和队列8¾判断栈是否为空栈Status StackEmpty_Sq(Stack S){ if(S.top==S.base) return TRUE;else return FALSE;}¾获得栈的实际长度int StackLength_Sq(Stack S){return(abs(S.top-S.base));}数据结构之栈和队列9¾多个栈共享邻接空间两个栈共享一空间::::::top1top21m中间可用空间栈1栈2地址Base1Base 2……数据结构之栈和队列103. 3 栈与递归¾递归函数:一个直接调用自己或通过一系列的调用语句间接地调用自己的函数。
第3章栈和队列-数据结构与算法(第2版)-汪沁-清华大学出版社

an
队头
队尾
队列示意图
入队
13
2、队列的基本运算
初始化队列 INIQUEUE(&Q)
将队列Q设置成一个空队列。
入队列
ENQUEUE(&Q,X)
将元素X插入到队尾中,也称“进队” ,“插入”。
出队列
DLQUEUE(&Q)
将队列Q的队头元素删除,也称“退队”、“删除”。
取队头元素 GETHEAD(Q)
也就是说,栈是一种后进先出(Last In First Out)的线性表,简称为LIFO表。
3
2、栈的运算
初始化栈:INISTACK(&S)
将栈S置为一个空栈(不含任何元素)。
进栈:PUSH(&S,X)
将元素X插入到栈S中,也称为 “入栈”、 “插入”、 “压 入”。
出栈: POP(&S)
删除栈S中的栈顶元素,也称为”退栈”、 “删除”、 “弹 出”。
9
三、链栈
typedef struct Lsnode { ElemType data;
struct Lsnode *next; } Lsnode *top;
一个链表栈由ቤተ መጻሕፍቲ ባይዱ顶指针top唯一确定。
10
1、链栈的主要运算
进栈操作 void Push(Lsnode *top; ElemType x)
{ p=(Lsnode *)malloc(sizeof(Lsnode)); p->data=x; p->next=top->next; top->next=p; }/*Push*/
第3章 栈和队列
1
栈和队列是二种特殊的线性表。是操作受 限的线 性表。 一、栈
《数据结构(C语言)》第3章 栈和队列

栈
❖ 栈的顺序存储与操作 ❖ 1.顺序栈的定义
(1) 栈的静态分配顺序存储结构描述 ② top为整数且指向栈顶元素 当top为整数且指向栈顶元素时,栈空、入栈、栈满 及出栈的情况如图3.2所示。初始化条件为 S.top=-1。
(a) 栈空S.top==-1 (b) 元素入栈S.stack[++S.top]=e (c) 栈满S.top>=StackSize-1 (d) 元素出栈e=S.stack[S.top--]
/*栈顶指针,可以指向栈顶
元素的下一个位置或者指向栈顶元素*/
int StackSize; /*当前分配的栈可使用的以 元素为单位的最大存储容量*/
}SqStack;
/*顺序栈*/
Data structures
栈
❖ 栈的顺序存储与操作 ❖ 1.顺序栈的定义
(2) 栈的动态分配顺序存储结构描述 ① top为指针且指向栈顶元素的下一个位置 当top为指针且指向栈顶元素的下一个位置时,栈空 、入栈、栈满及出栈的情况如图3.3所示。初始化条 件为S.top=S.base。
…,n-1,n≥0} 数据关系:R={< ai-1,ai>| ai-1,ai∈D,i=1,2
,…,n-1 } 约定an-1端为栈顶,a0端为栈底 基本操作:
(1) 初始化操作:InitStack(&S) 需要条件:栈S没有被创建过 操作结果:构建一个空的栈S (2) 销毁栈:DestroyStack(&S) 需要条件:栈S已经被创建 操作结果:清空栈S的所有值,释放栈S占用的内存空间
return 1;
}
Data structures
栈
第三章栈和队列

续8
//循环队列实现方案二 在SqQueue结构体中增设计数变量c,记录队列中当前 元素个数 void clearQueue(SqQueue &q) { q.r=q.f=-1; q.c=0; //r=f=-1~n-1区间任意整数均可 } int empty(SqQueue &q) { return q.c==0; } int full(SqQueue &q) { return q.c==q.n; } //队空、队满时q.f==q.r均为真 //优点:队满时没有空闲元素位置(充分利用了空间)
西南交通大学信息科学与技术学院软件工程系‐赵宏宇 数据结构A 第3章‐19
西南交通大学信息科学与技术学院软件工程系‐赵宏宇
数据结构A 第3章‐20
3.3 栈的应用
续1
3.3 栈的应用
续2
2. 栈与递归 (1) 递归程序的存储空间消耗 由于函数调用的指令返回地址、形式参数以及断 点状态均用系统堆栈实现存储,因此递归调用的层次 数(深度)决定了系统堆栈必须保留的存储空间容量大小。 例1 以下函数用递归法实现n元一维数组元素逆序存储, 试分析所需栈的深度。 void reverse(ElemTp a[], int i, int j) //数组a下标范围i..j实现元素逆序存储 { if(i<j) { a[i]a[j]; reverse(a, i+1, j-1); } }
西南交通大学信息科学与技术学院软件工程系‐赵宏宇 数据结构A 第3章‐7
3. 堆栈习题举例 例1 若元素入栈次序为ABC,写出所有可能的元素出栈 次序。 答: 所有可能的元素出栈次序共5种,即 ABC 操作PXPXPX (P表示入栈,X表示退栈) ACB PXPPXX BAC PPXXPX BCA PPXPXX CBA PPPXXX
第3章_栈和队列

(Chapter 3. பைடு நூலகம்tack and Queue)
栈的概念、存储结构及其基本操作
栈的应用举例 队列的概念、存储结构及其基本操作
§3.1 栈
3.1.1 栈的定义及基本运算
• 定义:只能在表尾(栈顶)进行插入和删除操 作进行的线性表。 • 特点: 后进先出(LIFO—Last In First Out )
top 栈顶
an an-1
. . .
a1 ∧
栈底
空栈: top == NULL
16
入栈
LinkStack Push_LS (LinkStack top,datatype x) { StackNode *p ; top p = (StackNode *) malloc (sizeof( StackNode)); p->data = x; top p->next = top; top = p; return top; }
23
2
括号匹配的检验:
问题:两种括号,可以嵌套使用,但不能重叠 解决:使用栈。 {([ ][ ])} 左括号进栈, 右括号就从栈顶出栈一个左括号, 检查是否能够匹配。 算法开始和结束时,栈都应该是空的。
匹配一个字符串中的左、右括号。如
[ a * ( b + c ) + d ]
( 出栈
( )匹配
[ 出栈
3.1.2 栈的存储及运算实现
顺序栈 -- 栈的顺序存储表示 链栈 -- 栈的链式存储表示
4
1 顺序栈
顺序栈类型的定义 – 本质 顺序表的简化,唯一需要确定的是栈顶、栈底。 – 通常 栈底:下标为0的一端 栈顶:由top指示,空栈时top=-1
第3章 栈和队列

例五、 表达式求值 例五、
限于二元运算符的表达式定义:
操作数) 运算符 运算符) 操作数 操作数) 表达式 ::= (操作数 + (运算符 + (操作数 操作数 操作数 ::= 简单变量 | 表达式 简单变量 :: = 标识符 | 无符号整数
表达式的三种标识方法: 表达式的三种标识方法: 设 Exp = S1 + OP + S2 则称 OP + S1 + S2 S1 + OP + S2 S1 + S2 + OP 为前缀表示法 前缀表示法 为中缀表示法 中缀表示法 为后缀表示法 后缀表示法
例如:(1348)10 = (2504)8 ,其 例如: 运算过程如下:
计 算 顺 序
N N div 8 N mod 8 1348 168 4 168 21 0 21 2 5 2 0 2
输 出 顺 序
void conversion () { InitStack(S); scanf ("%d",&N); while (N) { Push(S, N % 8); N = N/8; } while (!StackEmpty(S)) { Pop(S,e); printf ( "%d", e ); } } // conversion
栈和队列是两种常用的数据类型
3.1 栈的类型定义 3.2 栈的应用举例 3.3 栈类型的实现 3.4 队列的类型定义 3.5 队列类型的实现
3.1 栈的类型定义
ADT Stack { 数据对象: 数据对象 D={ ai | ai ∈ElemSet, i=1,2,...,n, n≥0 } 数据关系: 数据关系 R1={ <ai-1, ai >| ai-1, ai∈D, i=2,...,n } 约定an 端为栈顶,a1 端为栈底。 基本操作: 基本操作: } ADT Stack
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
队头/读出端
队尾/写入端
六、队列
优先队列
第 三 章 栈 与 队 列
队列中的元素按照关键字有序排列。 出队操作与一般队列相同,入队操作相当于 有序表的插入操作。
七、队列应用举例
由事件驱动的程序
第 三 章 栈 与 队 列
系统依靠事件驱动工作,即系统的工作过 程就是对所发生事件的响应处理过程。
3:13 1:21
2:23
1:13
六、队列
队列的定义
第 三 章 栈 与 队 列
队列是在一端进行插入(入队)操作,另一 端进行删除(出队)操作的线性表。
ABCD EF
六、队列
顺序结构实现的队列——循环队列
第 三 章 读出 栈 与 队 列 写入
六、队列
链式结构实现的队列
第 三 章 栈 与 队 列
五、栈与递归
汉诺塔问题
第 三 章 栈 与 队 列 1 2 3
五、栈与递归
汉诺塔问题
第 三 章 栈 与 队 列
问题的形式 递归规则
将n个片从a经b移到c
1、将n-1个片从a经c移到b; 2、将最后1个片从a移到c; 3、将n-1个片从b经a移到c; 如果n小于等于0,不须移动;
终结条件
1 出栈 2 3 入栈 4 5
操作:PPPQPPQQQQ 操作:PPPQPP 操作:PPPQ 操作:PPP 操作:
一、栈的定义
第 三 章 栈 与 队 列
设入栈序列为1 2 3 4 5 设用P表示Push,用Q表示Pop 问题:得到出栈序列4 3 1 2 5的操作序列 是?
1 出栈 2 3 入栈 4 5
第三章 栈与队列
一、栈的定义
第 三 章 栈 与 队 列
栈是只允许在一端进行插入和删除操作 的线性表。
入栈
出栈
栈顶 栈底
一、栈的定义
栈的基本操作
第 三 章 栈 与 队 列
Push(S, e):进栈/入栈 Pop(S):出栈/弹栈 GetTop(S):取栈顶元素 EmptyStack(S):判断栈空
七、队列应用举例
由事件驱动的程序
第 三 章 栈 与 队 列
银行业务模拟系统
柜台 柜台 柜台 柜台
七、队列应用举例
由事件驱动的程序
第 三 章 栈 与 队 列
银行业务模拟系统
顾客到达银行
选择一个人数最少的柜台排队,如果该柜台没有人,则 直接开始办理业务,并准备该顾客的业务完成事件。 如果未到下班时间,则准备下一个顾客到达银行的事件。
输入表达式为:12+(8-6)/2,预处理后为:12+(8-6)/2#
运算符栈
# # 12
操作数栈
当前词
12 +
操作
入栈 入栈
+ #
12
12 8 8 6 8 12 12 12
(
8 6 )
入栈
入栈 入栈 入栈 计算
第 三 章 栈 与 队 列
( + # ( + # - ( + # - ( + #
( + # + #
< X <
< X <
< X <
= X X
X > =
四、栈的应用举例
表达式计算问题
第 三 章 栈 与 队 列
算法如下:
E1:设立运算符栈和操作数栈; E2:开始运算符#入栈,向表达式串尾添加结束运算符#; E3:逐词读入表达式,并处理: E31:若读入为操作数,则入栈; E32:若读入为运算符,则与栈顶运算符相比较: E321:重复E321,直到栈顶运算符优先级不高于读入运算符: 弹出运算符,弹出两个操作数,计算并将结果入栈; E322:若栈顶运算符优先级低于读入运算符, 则将读入运算符入栈; E323:若栈顶运算符优先级等于读入运算符, 则弹出运算符,若遇到结束运算符,则计算结束。 E4:检查栈状态,得到计算结果;
a+b-
记:‘+’ > ‘-’
四、栈的应用举例
表达式计算问题
第 三 章 栈 与 队 列
以+、-、*、/、(、)为例,优先级表如下所示:
+ * /
+ > > > >
> > > >
* < < > >
/ < < > >
( < < < <
) > > > >
# > > > >
( ) #
< X <
< X <
顾客业务完成
顾客完成业务离开,下一个顾客开始办理业务,并准备 该队列中下一个顾客的业务完成事件。
七、队列应用举例
由事件驱动的程序
第 三 章 栈 与 队 列
银行业务模拟系统
初始化事件队列; 起始事件(第一个顾客到达事件)入队; 循环,直至事件队列空 事件出队; 若为到达事件,则 选择人数最少的柜台排队; 若该柜台无人排队,则业务完成事件入队; 若未到下班时间,则下一个顾客到达事件入队; 若为业务完成事件,则 顾客离开; 若该柜台还有人排队,则准备下一个人的业务完成事件;
五、栈与递归
函数调用的工作机制
第 三 章 栈 与 队 列
E1: E2: E3: E4: E5:
参数入栈 返回地址入栈 跳转到函数入口,开始执行函数 函数结束时,从栈中弹出返回地址 返回调用点并清空栈中的参数
以汉诺塔递归求解过程为例, 调用Hanoi( 3, 1, 2, 3 ),递归过程如下:
N! = N * (N-1)! long FN( long N ) { if( N<=1 ) return 1; else return N * FN( N-1 ); }
五、栈与递归
递归三要素
第 三 章 栈 与 队 列
1、问题的形式
long FN( long N )
2、递归的规则
return N * FN(N-1);
第 三 章 栈 与 队 列
0 1 2 3 ... n-1 入栈
栈底
栈顶
出栈
பைடு நூலகம்
三、链式结构实现的栈
第 三 章 栈 与 队 列
入栈
栈顶
栈底 ^
出栈
四、栈的应用举例
括号匹配问题
第 三 章 栈 与 队 列
检查指定的表达式串中的括号是否配对 将指定整数转换为指定基数的数字串
进制转换问题
四、栈的应用举例
表达式计算问题
第 三 章 栈 与 队 列
计算由常数和二元运算符、括号组成的四则运算表 达式
((12.3-9)/2.2+(15+3.1)*0.3)/1.3
四、栈的应用举例
表达式计算问题——算符优先级算法
第 三 章 栈 与 队 列
设可用运算符有+-*/(),定义#作为起始和 结束运算符
根据运算符优先级构造优先级表M[n][n],其中n a+b* 记:‘+’ < ‘*’ 为可用运算符个数(包括#),M[i][j]的意义为 当运算符Oi遇到运算符Oj时,Oi是否可以运算,可 a+( 记:‘+’ < ‘(’ 以运算则记为Oi>Oj,否则记为Oi<Oj,特殊情况 a+b) 记:‘+’ > ‘)’ 另记。
3、终结条件
if( N<=1 ) return 1;
五、栈与递归
例:设计程序,计算下式。
第 三 章 栈 与 队 列
m n 1 f ( m, n ) n m 1 f ( m 1, n) f ( m, n 1) m 1, n 1
f(3,2) = = = = f(2,2)+f(3,1) f(1,2)+f(2,1)+f(3,1) 2+2+3 7
操作:PPPPQQ 操作:PPPP 操作:
一、栈的定义
第 三 章 栈 与 队 列
问题:对给定的入栈序列1 2 3 … n, 什么样的出栈序列是得不到的?
出栈序列可以看作是1…n的一个排列, 设为:p1p2p3…pn,若存在i<j<k,使得: pj<pk<pi,则该序列不能通过栈操作得到。
二、顺序结构实现的栈
1:13
2:12
1:32
(B,0,3,2,1) (A,0,2,1,3) (B,0,1,3,2) (A,0,3,2,1) (B,0,2,1,3) (A,0,1,3,2) (B,1,1,2,3) (A,1,2,3,1) (B,1,3,1,2) (A,1,1,2,3) (B,2,2,1,3) (A,2,1,3,2) (-,3,1,2,3) (X,n,a,b,c)
/ + # / + # + # # 2
2 2
2 2 1
12 12
12 12 12 13
) /
2 # # #
抵消 入栈
入栈 计算 计算 结束
五、栈与递归
递归
第 三 章 栈 与 队 列
函数直接或间接调用自身称为递归调用。 当问题可以被分解为同类型的、规模更小的子问题时,可递 归求解子问题,再由子问题的解得到原问题的解。