数据结构 第三章 栈和队列

合集下载

数据结构课件第3章

数据结构课件第3章

0
1
2
3
4
5
6
7
a1
a2
a3
a4
a5
a6
a7
队头 F=0
队尾 R=7
a3 2 1 3 0 4 7 a3 5 6 3 a2 2 1 a1 0 F=0 a4 4 a5 5 6 a6 7 a7 R=0 R=7 3 a2 2 1 a1 0
a4 4 a5 5 6 a6 7
a8
F=0
a7
R=0
F=0
删除所有元素
top X W … B top
top=0 空栈
top
W

B A
top=m-1 元素X出栈
top
A
A
top=m 满栈
top=1 元素A入栈
例:堆栈的插入、删除操作。 出栈操作程序如下: # define m 1000; /*最大栈空间*/ 出栈操作算法: 1)栈顶指针top是否为0: typedef struct stack_stru 若是,则返回;若不是, { int s[m]; int top; }; 则执行2。 void pop (stack, y) 2)将栈顶元素送给y, struct stack_stru stack; 栈顶指针减1。 int *y; { if (stack.top = = 0) printf (“The stack is empty ! \n”); top Y Y else { top B B *y=stack.s[stack.top]; A A stack.top - -; } 出栈操作 }
top=p;
} 栈的入栈、出栈操作的时间复杂度都为O(1)。
栈的应用
一、 表达式求值 表达式由操作数、运算符和界限符组成。 运算符可包括算术运算符、关系运算符、逻辑运算符。

大学数据结构课件--第3章 栈和队列

大学数据结构课件--第3章 栈和队列
top top 栈空 F E D C B A
栈满 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

数据结构栈和队列ppt课件

数据结构栈和队列ppt课件

栈的运用 例3.1 将一个十进制正整数N转换成r进制的数
N 〕
1835
229
28
3
N / 8 〔整除〕 N % 8〔求余
229
3

28
5
3
4
0
3

❖例3.2 算术表达式中括号匹配的检查
❖用栈来实现括号匹配检查的原那么是,对表达式从左 到右扫描。
❖〔1〕当遇到左括号时,左括号入栈;
❖〔2〕当遇到右括号时,首先检查栈能否空,假设栈 空,那么阐明该“右括弧〞多余;否那么比较栈顶左 括号能否与当前右括号匹配,假设匹配,将栈顶左括 号出栈,继续操作;否那么,阐明不匹配,停顿操作 。
❖在顺序栈上实现五种根本运算的C函数 ❖〔3〕入栈 ❖int push (SeqStack *s, DataType x) ❖{ if (s->top==MAXSIZE-1) /*栈满不能入栈*/ ❖{ printf("overflow"); ❖return 0; ❖} ❖ s->top++; ❖ s->data[s->top]=x; ❖ return 1; ❖}
链队列及运算的实现
采用链接方法存储的队列称为链队列〔Linked Queue〕
采用带头结点的单链表来实现链队列,链队列中 的t结ype点de类f st型ruc与t N单od链e 表一样。将头指针front和尾指针 re{arD封at装aTy在pe一da个ta;构造体中,链队列用C言语描画如 下:struct Node *next;
❖只设了一个尾指针r ❖头结点的指针,即r->next ❖队头元素的指针为r->next->next ❖队空的断定条件是r->next==r

《数据结构(C语言)》第3章 栈和队列

《数据结构(C语言)》第3章 栈和队列
Data structures

❖ 栈的顺序存储与操作 ❖ 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

数据结构第三章 栈和队列

数据结构第三章  栈和队列

计 3467
433
算 433
54
顺 54
6

6
0
3
低输
1

6

6
高序
所以:(3467)10 =(6613)8
28
算法思想:当N>0时重复1,2 1. 若 N≠0,则将N % r 压入栈s中 ,执行2;
若N=0,将栈s的内容依次出栈, 算法结束。 2. 用N / r 代替 N
29
【算法3-10】数制转换算法一
队满时 m=maxsize,队空时m=0
front rear
data
0
a1
1
a2
2
a3


n-1
an


Max-1
Top=-1,B、A出栈
13
顺序栈的主要运算
• 特殊情况表示: • 栈空:top == -1 • 栈满:top == maxsize-1
• 运算实现: • 入栈:若栈不满 s->top++ ; • 出栈:若栈不空 s->top-- ;
14
⑴ 置空栈
【算法3-1】栈的初始化算法 SeqStack *Init_SeqStack(){
若空则出错 (2)获取栈顶元素 x (3)栈顶指针减1
int Pop_SeqStack(SeqStack *s,DataType x){ if (Empty_SeqStack(s)) return 0; //栈空不能出栈,返回错误代码0 else { x=s->data[s->top]; //保存栈顶元素值
typedef struct {
datatype data[maxsize];

数据结构课件第3篇章栈和队列

数据结构课件第3篇章栈和队列

循环队列实现原理
01
循环队列定义
将一维数组看作首尾相接的环形结构,通过两个指针(队头和队尾指针)
在数组中循环移动来实现队列的操作。当队尾指针到达数组末端时,再
回到数组起始位置,形成循环。
02
判空与判满条件
在循环队列中,设置一个标志位来区分队列为空还是已满。当队头指针
等于队尾指针时,认为队列为空;当队尾指针加1等于队头指针时,认
栈在函数调用中应用
函数调用栈
在程序执行过程中,每当发生函数调用时,系统会将当前函数的执行上下文压入一个专门的栈中,称为函数调用 栈。该栈用于保存函数的局部变量、返回地址等信息。当函数执行完毕后,系统会从函数调用栈中弹出相应的执 行上下文,并恢复上一个函数的执行状态。
递归调用实现
递归调用是一种特殊的函数调用方式,它通过在函数调用栈中反复压入和弹出同一函数的执行上下文来实现对问 题的分解和求解。在递归调用过程中,系统会根据递归深度动态地分配和管理函数调用栈的空间资源。
栈和队列的应用
栈和队列在计算机科学中有着广泛的应用,如函数调用栈、表达式求 值、缓冲区管理等。
常见误区澄清说明
误区一
栈和队列的混淆。虽然栈和队列都是线性数据结构,但它们的操作方式和应用场景是不同的。栈是后进先出,而队列 是先进先出。
误区二
认为栈和队列只能通过数组实现。实际上,栈和队列可以通过多种数据结构实现,如链表、循环数组等。具体实现方 式取决于应用场景和需求。
后缀表达式求值
利用栈可以方便地实现后缀表达式的求值。具体步骤 为:从左到右扫描表达式,遇到数字则入栈,遇到运 算符则从栈中弹出所需的操作数进行计算,并将结果 入栈,最终栈中剩下的元素即为表达式的结果。
中缀表达式转换为后缀表达式

数据结构第三章 数据结构堆栈和队列

数据结构第三章数据结构堆栈和队列数据结构第三章数据结构堆栈和队列3.1 堆栈堆栈(Stack)是一种遵循后进先出(Last In First Out,LIFO)原则的线性数据结构。

堆栈中只有一个入口,即栈顶,所有的插入和删除操作都在栈顶进行。

3.1.1 堆栈的基本操作- Push:将元素插入到栈顶- Pop:从栈顶删除一个元素- Top:获取栈顶元素的值- IsEmpty:判断栈是否为空- IsFull:判断栈是否已满3.1.2 堆栈的实现堆栈可以使用数组或链表来实现。

- 基于数组的堆栈实现:使用一个数组和一个指针来表示堆栈,指针指向栈顶元素的位置。

Push操作时,将元素插入到指针指向的位置,然后将指针向上移动;Pop操作时,将指针指向的元素弹出,然后将指针向下移动。

- 基于链表的堆栈实现:使用一个链表来表示堆栈,链表的头结点表示栈顶元素。

Push操作时,创建一个新节点并将其插入链表的头部;Pop操作时,删除链表的头结点。

3.1.3 堆栈的应用堆栈广泛应用于各种场景,如函数调用栈、表达式求值、括号匹配等。

3.2 队列队列(Queue)是一种遵循先进先出(First In First Out,FIFO)原则的线性数据结构。

队列有两个端点,一个是入队的端点(队尾),一个是出队的端点(队首)。

3.2.1 队列的基本操作- Enqueue:将元素插入到队尾- Dequeue:从队首删除一个元素- Front:获取队首元素的值- Rear:获取队尾元素的值- IsEmpty:判断队列是否为空- IsFull:判断队列是否已满3.2.2 队列的实现队列可以使用数组或链表来实现。

- 基于数组的队列实现:使用一个数组和两个指针来表示队列,一个指针指向队首元素,一个指针指向队尾元素的下一个位置。

Enqueue操作时,将元素插入到队尾指针所指向的位置,然后将队尾指针向后移动;Dequeue操作时,将队首指针指向的元素弹出,然后将队首指针向后移动。

数据结构第三章 堆栈和队列

第三章堆栈和队列3.1 栈3.1.1 栈的定义及基本运算栈和队列是两种特殊的线性表,它们的逻辑结构和线性表相同,只有其运算规则较线性表有更多的限制,故又称它们为运算受限的线性表。

栈的定义栈(Stack):是限制仅在表的一端进行插入和删除运算的线性表,通常称插入、删除的这一端为栈顶(Top),另一端称为栈底(Bottom)。

栈的修改是按后进后出的原则进行的。

因此,栈又称为后进先出(Last In First Out)的线性表,简称为LIFO表。

栈的基本运算InitStack(S) 构造一个空栈S。

StackEmpty(S) 判栈空。

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

StackFull(S) 判栈满。

若S为满栈,则返回TRUE,否则返回FALSE。

该运算只适用于栈的顺序存储结构。

Push(S,x) 进栈。

若栈S不满,则将元素x插入S的栈顶。

Pop(S) 退栈。

若栈S非空,则将S的栈顶元素删去,并返回该元素。

StackTop(S) 取栈顶元素。

若栈S非空,则返回栈顶元素,但不改变栈的状态。

3.1.2 顺序栈基本概念顺序栈:即栈的顺序存储结构,是利用一组地址连续的存储单元依次存放自栈底到栈顶的数据元素。

栈顶指针和栈中元素之间的关系基本算法在顺序栈上实现栈的六种基本运算,具体算法如下:置空栈判栈空判栈满进栈退栈取栈顶元素3.1.3 链栈链栈:栈的链式存储结构称为链栈。

链栈是运算受限的单链表,它的插入和删除被限制在表头位置上进行。

栈顶指针就是链表的头指针,它唯一确定一个链栈。

链栈上实现的基本运算:置空栈判栈空进栈退栈取栈顶元素3.2 队列3.2.1 队列的定义及基本运算队列的定义队列(Queue)也是一种运算受限的线性表。

它只允许在表的一端进行插入,而在另一端进行删除。

允许删除的一端称为队头(Front),允许插入的一端称为队尾(Rear)。

队列的修改是按先进先出的原则进行的。

因此,队列又称为先进先出(First In First Out)的线性表,简称为FIFO表。

数据结构 3栈和队列


第3章 栈和队列
4. 顺序栈的输出
将顺序栈中当前的元素值输出(从栈顶开始输出) ➊ 程序实现
/*=================================== 函数功能:顺序栈输出 函数输入:顺序栈地址 函数输出:无 ====================================*/ void PrintStack(SeqStack *s) { int i; if(Empty_SeqStack(s)==1) //栈空不输出 { printf("顺序栈为空\n"); exit(1); } else for(i=s->top;i>=0;i--) printf("%4d",s->data[i]); }
第3章 栈和队列
顺序栈和链栈的比较
时间效率
空间效率
顺序栈
链式栈 说明
所有操作都只需常数时间
链式栈在栈顶操作,效率很高
顺序栈须长度固定
链式栈的长度可扩展,但增加结构性 开销
顺序栈和链式栈在时间效率上难 实际应用中,顺序栈比链式栈用得更 分伯仲 广泛些
顺序栈的缺点是栈满后不 能再进栈,链栈无栈满问 题(系统资源足够时)。
第3章 栈和队列
/*================================= 函数功能:链栈的进栈操作 函数输入:(栈顶指针)、进栈元素 函数输出:栈顶指针 =================================*/ LinkStack Push_LinkStack(LinkStack top, ElemType x ) { LinkStack p; p=(LinkStack)malloc( sizeof(StackNode) ); p->data=x; p->next=top; top= p; return top; }

第3章栈和队列

第3章栈和队列

3.1.2 栈的表示和算法实现
1.顺序栈 2.链栈
第3章栈和队列
1. 顺序栈 顺序栈是用顺序存储结构实现的栈,即利 用一组地址连续的存储单元依次存放自栈 底到栈顶的数据元素,同时由于栈的操作 的特殊性,还必须附设一个位置指针top( 栈顶指针)来动态地指示栈顶元素在顺序 栈中的位置。通常以top=-1表示空栈。
第 3 章 栈和队列
3.1 栈 3.2 队列 3.3 栈和队列的应用
第3章栈和队列
3.1 栈
3.1.1 栈的抽象数据类型定义 3.1.2 栈的表示和算法实现
第3章栈和队列
3.1.1 栈的定义
1.栈的定义 栈(stack)是一种只允许在一端进行插入和删除的线 性表,它是一种操作受限的线性表。在表中只允许进
行插入和删除的一端称为栈顶(top),另一端称为 栈 底 (bottom) 。 栈 的 插 入 操 作 通 常 称 为 入 栈 或 进 栈 (push),而栈的删除操作则称为出栈或退栈(pop)。 当栈中无数据元素时,称为空栈。
栈是按照后进先出 (LIFO)的原则组 织数据的,因此, 栈也被称为“后进 先出”的线性表。
第3章栈和队列
(2)入栈操作
Status Push(SqStack &S, Elemtype e)
【算法3.2 栈的入栈操作】
{ /*将元素e插入到栈S中,作为S的新栈顶*/
if (S->top>= Stack_Size -1) return ERROR;
else { S->top++;
S->elem[S->top]=e;
return OK;}
Push(S,’you’)
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

二、队列的链式存储结构 两个指针变量:头指针和尾指针, 设一个存放 队头指针和队尾指针的结点;队首元素前附加一 个头结点,头指针指向头结点;无队满现象。 typedef struct qnode data next {ET data; 头结点 q->front struct qnode *next; }QNODE; 队头元素 typedef struct lqueue ...... {QNODE *front, *rear; }LQUEUE;
判栈空 int empty(Sqstack s) { if(s.top==0 return 1; else return 0;)} 取栈顶元素 int gettop(Sqstack s, int x) { if(s.top==0) return ERROR; else {x=s.elem[s.top] return x;}} main() {Sqstack stack; int m; int i; i=gettop(stack, m); if(i==0) printf(“没取到”); else printf(“%d”,i);}
(头)
4、栈的基本运算: 入栈:push(S,x) 把x推入栈S 出栈:pop(S,x) 把栈顶元素赋给x,并删除 该栈顶元素 取栈顶元素:gettop(S, x)取出栈顶元素送给x 判栈空:empty(S) 栈空返回1,否则为0 栈初始化:initstack(S) 初始化空栈
二、栈的顺序存储 用一组地址连续的内存单元存放自栈底到 栈顶的数据元素,同时附设一个栈顶指针 top(是整型变量),通常top=0表示空栈。 用代码定义并实现各运算: #define true 1 #define false 0 #define ERROR 0 #define OK 1 #define maxsize 100
实例: 用带表头结点的单循环链表来表示队列, 并且设一个指向队尾元素的指针rear,写出 其入列和出队的运算。
d1 q d2 d3 d4 d5 rear
typedef struct qnode { int data; struct qnode *next;}Qnode;
void initqueue(Qnode *p) {p=(Qnode *)malloc(sizeof(Qnode)); p->next=p;} void enqueue( int x, Qnode *rear) {Qnode *q; q=(Qnode *)malloc(sizeof(Qnode)); q->data=x; q->next=rear->next; rear->next=q; rear=q; }
-1
0
1
2
3
入队
frontБайду номын сангаас非队中元素 )
rear(是队中元素)
几条重要原则 队列的初始化条件: q->rear=q->front=-1 队满条件: q->rear=MAXSIZE-1 队空条件: q->front=q->rear 各种运算
5 4 3 2 1 0 q->rear q->front (a) q->front (b) (c) (d) q->rear 5 4 3 5 4 3 q->rear q->front 2 q->front 1 0 q->rear
栈底
进栈: Linkstack *push(Linkstack *top, char x) { Linkstack *p; p=malloc(sizeof(Linkstack)); p->data=x; p->next=top; top=p; return p; }
出栈: Linkstack *pop(Linkstack *top, char ch)) { Linkstack *p; if(top==NULL) printf(“链表中无元素\n”); else {ch=top->data; p=top; top=top->next; free(p);} return top; }
q->rear q->front
x
0
出队列: int delq(SQUEUE *q, int x) {if(q->front=q->rear) return 0; else {q->front++; x=q->data[q->front]; return 1; } q->rear } x q->front
q->rear
^
队尾元素
运算的实现: 入队:在队列q的尾部插入一个值为x的结点p
p q->front d1 q->rear x ^
addq(LQUEUE *q,int x) { QNODE *p; p=(QNODE *)malloc(sizeof(QNODE)); p->data=x; p->next=NULL; (*q).rear->next=p; (*q).rear=p;}
栈的定义描述: typedef struct stack { ET elem[maxsize]; int top; /*栈顶指针,用来表示数组的下标*/ }Sqstack; 实现各种运算: 栈初始化 void initstack(Sqstack s) { s.top=0;} main() { Sqstack stack; initstack(stack);}
5 4 3 2 1 0
求队列元素的个数: int count(SQUEUE q) {int i; i=q.rear-q.front; return i; }
四、循环队列 q->rear F 5 1、问题提出:如右图所示, E 4 q->rear=MAXSIZE-1时队满, D 3 2 q->front 但实际上存在无法利用的空 1 间,即为假满现象。 0 2、处理方法: 1)元素前移; 2)把队列看成首尾相连的环,即循环队列。
三、队列的顺序存储结构 两个指针分别为队头指针front和队尾指针 rear , 是整型变量,头指针指向第一个元素的前一个单元 的位置,而尾指针指向最后一个元素的位置。
出队
类型说明: #define MAXSIZE 100 typedef struct squeue { ET data[MAXSIZE]; int front,rear; }SQUEUE;
出栈 int pop(Sqstack s, int x ) {if(empty(s)) return ERROR; else {x=s.elem[s.top]; s.top- -; return x;} } main() {Sqstack stack; int m; int i; i=pop(stack,m); printf(“%d%d”,i,stack.top) }
空队列:
q->front ^ q->rear
int emptyq(LQUEUE q) {if(q.front=q.rear) return 1; else return 0; }
出队列: 删除q的队头元素,并由x返回队头元素的值.
q->front d1 q->rear p d2 ^
void delq(LQUEUE *q,int x) {QNODE *p; if(empty(q)) printf(“队列为空”); else{p=q->front->next; x=p->data; (*q).front->next=p->next; if(p->next==NULL) q->rear=q->front;//判是否为空 free(p);}}
入栈: int push(Sqstack s , int x) {if(s.top==maxsize-1) return ERROR; else {s.top++; s.elem[s.top]=x; return OK;}} 说明: 如要返回整个栈时,则改为: int *push(Sqstack s, int x) { ...... Return s;...... }
F E D
5 4 3 2 1 0
C B A
2 1 0
入队:把x加入队列q中去 void addq(SQUEUE *q, int x) {if(q->rear==MAXSIZE-1) printf(“队满”); else 5 { q->rear++; 4 q->data[q->rear]=x; 3 } 2 } 1
void delqueue(Qnode *rear) { Qnode *p; if(rear->next!=rear) { q=rear->next; p=q->next;q->next=p->next; if(p==rear) {q->next=q;rear=q;} free(p); } }
主调函数: #include “stdio.h” #include “stdlib.h” main() { Qnode *p; int i; initqueue(p); scanf(“%d”,&i); enqueue(i,p); delqueue(p); } 上机作业:完成程序并调试成功。
a1 a2 a3 a4 ...... an 队头 队尾
入队
4、运算操作 入队:addq(q,x) 在队尾插入元素x; 出队:delq(q,x) 删除q的队头元素,并由x返回; 取队头元素:frontq(q,x) 把队头元素放入参 数x中,并由其返回; 判队列为空:emptyq(q) 队列为空返回true,否 则返回false;
3.2队列(queue) 一、队列的定义与运算 1、只允许中一端进行插入,在另一端进行删 除的线性表,first in first out 简称:FIFO 2、允许插入的端为队尾(rear),允许删除 的端为队头(front); 3、构成队列的三要素: 1)存储队列元素的空间; 出队 2)队头、队尾指针。
相关文档
最新文档