数据结构详细讲解(栈和队列)
数据结构-栈与队列

栈 1.6栈的应用
运算符的优先级关系表在运算过程中非常重要,它是判定进栈、出栈的重要依据。
θ1
θ2
+
-
+
>
>
-
>
>
*
>
>
/
>
>
(
<
<
)
>
>
#
<
<
*
/
(
)
#
<
<
<
>
>
<
<
<
>
>
>
>
<
>
>
>
>
<
>
>
<
<
<
=
>
>
>
>
<
<
<
=
栈
1.6栈的应用
下面以分析表达式 4+2*3-12/(7-5)为例来说明求解过程,从而总结出表达式求值的算 法。求解中设置两个栈:操作数栈和运算符栈。从左至右扫描表达式:# 4+2*3-12/(7-5) #, 最左边是开始符,最右边是结束符。表达式求值的过程如下表所示:
1.4栈的顺序存储结构
设计进栈算法——Push 函数。首先,判断栈是否已满,如果栈已满,就运用 realloc 函 数重新开辟更大的栈空间。如果 realloc 函数返回值为空,提示溢出,则更新栈的地址以及栈 的当前空间大小。最终,新元素入栈,栈顶标识 top 加 1。
栈和队列数据结构的特点

栈和队列数据结构的特点栈和队列是常用的数据结构,它们在程序设计和算法实现中有着重要的作用。
下面将分别介绍栈和队列的特点。
一、栈(Stack)的特点:1.先进后出(FILO):栈是一种只允许在栈顶进行插入和删除操作的线性数据结构。
元素的插入和删除都只能在栈顶进行,最后插入的元素是第一个被删除的元素。
2.后进先出(LIFO):栈中最后一个进栈的元素是第一个出栈的元素。
3.只能在栈顶进行操作:栈的操作局限于栈顶,在栈顶可以执行的操作有入栈和出栈操作,其他位置的元素无法直接访问和操作。
4.压入和弹出操作:在栈中,我们只能在栈的一端(通常是栈顶)进行数据的插入和删除操作,分别称为“压入”和“弹出”。
5.递归的应用:栈的结构特点使得它在递归算法的实现中非常有用。
递归函数调用时,每次进入一层递归都需要保存当前的状态,包括参数、局部变量等信息,在递归返回时再恢复状态。
6.存储空间的限制:栈的存储空间是有限的,当栈的元素数量超过了栈的容量时,就会发生栈溢出错误。
7.实现方式:栈可以使用数组或链表来实现。
栈的典型应用场景包括函数调用、表达式求值、括号匹配、迷宫求解等。
二、队列(Queue)的特点:1.先进先出(FIFO):队列是一种只允许在队尾插入操作,在队头删除操作的线性数据结构。
最先插入的元素是第一个被删除的元素,最后插入的元素是最后被删除的元素。
2.队头和队尾操作:队列的操作局限于队头和队尾,在队头可以执行的操作有删除,称为“出队”操作;在队尾可以执行的操作有插入,称为“入队”操作。
3.可用空间有限:队列的存储空间是有限的,当队列的元素数量超过了队列的容量时,就会无法再插入新的元素,即发生队列溢出错误。
4.实现方式:队列可以使用数组或链表来实现。
若使用链表实现的队列,可实现动态调整队列的大小。
队列的典型应用场景包括多线程任务调度、缓冲队列、消息队列等。
栈和队列都是特殊的线性数据结构,它们各自的特点使它们在不同的应用场景下得到广泛的应用。
数据结构(C语言)第3章 栈和队列

Data Structure
2013-8-6
Page 13
栈的顺序存储(顺序栈)
利用一组地址连续的存储单元依次存放自栈底到栈顶的数 据元素。 结构定义: #define STACK_INIT_SIZE 100; // 存储空间初始分配量 #define STACKINCREMENT 10; // 存储空间分配增量 typedef struct { SElemType *base; // 存储空间基址 SElemType *top; // 栈顶指针 int stacksize; // 当前已分配的存储空间,以元素位单位 } SqStack;
解决方案2:
顺序栈单向延伸——使用一个数组来存储两个栈
Data Structure 2013-8-6 Page 21
两栈共享空间 两栈共享空间:使用一个数组来存储两个栈,让一个 栈的栈底为该数组的始端,另一个栈的栈底为该数组 的末端,两个栈从各自的端点向中间延伸。
Data Structure
2013-8-6
链栈需要加头结点吗? 链栈不需要附设头结点。
Data Structure
2013-8-6
Page 27
栈的链接存储结构及实现
Data Structure
2013-8-6
Page 11
GetTop(S, &e) 初始条件:栈 S 已存在且非空。 操作结果:用 e 返回S的栈顶元素。 Push(&S, e) 初始条件:栈 S 已存在。 操作结果:插入元素 e 为新的栈顶元素。 Pop(&S, &e) 初始条件:栈 S 已存在且非空。 操作结果:删除 S 的栈顶元素,并用 e 返回其值。
Data Structure
数据结构--栈和队列基础知识

数据结构--栈和队列基础知识⼀概述栈和队列,严格意义上来说,也属于线性表,因为它们也都⽤于存储逻辑关系为 "⼀对⼀" 的数据,但由于它们⽐较特殊,因此将其单独作为⼀篇⽂章,做重点讲解。
既然栈和队列都属于线性表,根据线性表分为顺序表和链表的特点,栈也可分为顺序栈和链表,队列也分为顺序队列和链队列,这些内容都会在本章做详细讲解。
使⽤栈结构存储数据,讲究“先进后出”,即最先进栈的数据,最后出栈;使⽤队列存储数据,讲究 "先进先出",即最先进队列的数据,也最先出队列。
⼆栈2.1 栈的基本概念同顺序表和链表⼀样,栈也是⽤来存储逻辑关系为 "⼀对⼀" 数据的线性存储结构,如下图所⽰。
从上图我们看到,栈存储结构与之前所了解的线性存储结构有所差异,这缘于栈对数据 "存" 和 "取" 的过程有特殊的要求:1. 栈只能从表的⼀端存取数据,另⼀端是封闭的;2. 在栈中,⽆论是存数据还是取数据,都必须遵循"先进后出"的原则,即最先进栈的元素最后出栈。
拿图 1 的栈来说,从图中数据的存储状态可判断出,元素 1 是最先进的栈。
因此,当需要从栈中取出元素 1 时,根据"先进后出"的原则,需提前将元素 3 和元素 2 从栈中取出,然后才能成功取出元素 1。
因此,我们可以给栈下⼀个定义,即栈是⼀种只能从表的⼀端存取数据且遵循 "先进后出" 原则的线性存储结构。
通常,栈的开⼝端被称为栈顶;相应地,封⼝端被称为栈底。
因此,栈顶元素指的就是距离栈顶最近的元素,拿下图中的栈顶元素为元素 4;同理,栈底元素指的是位于栈最底部的元素,下中的栈底元素为元素 1。
2.2 进栈和出栈基于栈结构的特点,在实际应⽤中,通常只会对栈执⾏以下两种操作:向栈中添加元素,此过程被称为"进栈"(⼊栈或压栈);从栈中提取出指定元素,此过程被称为"出栈"(或弹栈);2.3 栈的具体实现栈是⼀种 "特殊" 的线性存储结构,因此栈的具体实现有以下两种⽅式:1. 顺序栈:采⽤顺序存储结构可以模拟栈存储数据的特点,从⽽实现栈存储结构。
数据结构实验三栈和队列的应用

数据结构实验三栈和队列的应用数据结构实验三:栈和队列的应用在计算机科学领域中,数据结构是组织和存储数据的重要方式,而栈和队列作为两种常见的数据结构,具有广泛的应用场景。
本次实验旨在深入探讨栈和队列在实际问题中的应用,加深对它们特性和操作的理解。
一、栈的应用栈是一种“后进先出”(Last In First Out,LIFO)的数据结构。
这意味着最后进入栈的元素将首先被取出。
1、表达式求值在算术表达式的求值过程中,栈发挥着重要作用。
例如,对于表达式“2 + 3 4”,我们可以通过将操作数压入栈,操作符按照优先级进行处理,实现表达式的正确求值。
当遇到数字时,将其压入操作数栈;遇到操作符时,从操作数栈中弹出相应数量的操作数进行计算,将结果压回操作数栈。
最终,操作数栈中的唯一值就是表达式的结果。
2、括号匹配在程序代码中,检查括号是否匹配是常见的任务。
可以使用栈来实现。
遍历输入的字符串,当遇到左括号时,将其压入栈;当遇到右括号时,弹出栈顶元素,如果弹出的左括号与当前右括号类型匹配,则继续,否则表示括号不匹配。
3、函数调用和递归在程序执行过程中,函数的调用和递归都依赖于栈。
当调用一个函数时,当前的执行环境(包括局部变量、返回地址等)被压入栈中。
当函数返回时,从栈中弹出之前保存的环境,继续之前的执行。
递归函数的执行也是通过栈来实现的,每次递归调用都会在栈中保存当前的状态,直到递归结束,依次从栈中恢复状态。
二、队列的应用队列是一种“先进先出”(First In First Out,FIFO)的数据结构。
1、排队系统在现实生活中的各种排队场景,如银行排队、餐厅叫号等,可以用队列来模拟。
新到达的顾客加入队列尾部,服务完成的顾客从队列头部离开。
通过这种方式,保证了先来的顾客先得到服务,体现了公平性。
2、广度优先搜索在图的遍历算法中,广度优先搜索(BreadthFirst Search,BFS)常使用队列。
从起始节点开始,将其放入队列。
第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
栈和队列是二种特殊的线性表。是操作受 限的线 性表。 一、栈
数据结构栈和队列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章 栈和队列

栈
❖ 栈的顺序存储与操作 ❖ 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
栈
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
4
栈的定义
定义:限定仅在表尾进行插入或删除操作 的线性表。 表尾—栈顶 表头—栈底 不含元素的空表称空栈
5
栈的特点
特点:先进后出(FILO)或后进先出(LIFO)
进栈 栈顶 出栈 ... an ……... a2 栈底 栈s=(a1,a2,……,an)
第三章 栈和队列
栈和队列
栈和队列是两种特殊的线性表 是操作受限的线性表,称为限定性的数据结构 栈的插入和删除限定在表尾 队列的插入限定在表尾,删除限定在表头
2
第3章 栈和队列
3.1 3.2 3.3 3.4
栈(Stack) 队列(Queue) 本章小结 课后练习
3
3.1 栈(Stack)
int IsEmpty ( SeqStack * s ) { if ( S->top= =-1 ) return 1; else return 0; }
20
顺序栈的判满
int IsFull ( SeqStack * s ) { if ( S->top = = Stack_Size-1 ) return 1; else return 0; }
4 3
2 1 top 0
4 3
2 1 0
D C
B
空栈
A 进栈
栈空时出栈,则下溢(underflow) 栈满时入栈,则上溢(overflow)
16
思考题
设有一个空栈,栈的首地址为1000H(十六进制) ,经过push,push,pop,push,pop,push,pop,push后 ,栈顶元素的地址为多少(sizeof(ElemType)=2)? 答案: 1002H
后缀表达式:435*+
4
3 4
5 3 4
15 4
19
45
栈的应用5—函数的调用
函数的嵌套调用
主 程 序 s 子 过 程 s t s
子 过 程 t
f t s
子 过 程 f
46
s
t s
default: return(FALSE);
} return(TRUE); }
31
链栈
链栈:栈的操作是线性表的特例,链栈的操作 易于实现。注意分析结点指针的指向。
ai
ai+1 top
ai+1
ai
^
空链栈 … 栈顶 a1 栈底
top
an
^
32
链栈结点类型
typedef struct node {
-12 操作数 运算符
后缀表达式求值
后缀表达式求值步骤(引入一个栈即可): 1.读入表达式一个字符 2.若是操作数,压入栈,转4 3.若是运算符,从栈中弹出2个数,将运算 结果再压入栈 4.若表达式输入完毕,栈顶即表达式值; 若表达式未输入完,转1
44
后缀表达式求值
例: 计算 4+3*5
4. IsFull(S) 6. Pop(S,x)
12
栈的表示和实现
栈在计算机中主要有两种基本的存储结构: 顺序存储结构和链式存储结构。 顺序存储的栈称为顺序栈 链式存储的栈称为链栈
13
顺序栈
顺序栈:利用一组地址连续的存储单元依次存 放自栈底到栈顶的数据元素,同时附设指针 top指示栈顶元素在顺序栈中的位置。 顺序栈的类型说明: typedef struct { ElemType elem[Stack_Size]; int top; }SeqStack;
a1
6
入栈序列与出栈序列
栈具有LIFO性质,若已知栈的输入序列为1 2 3 ,则输出序列有多少种呢? 以1为头:123 132 以2为头:213 231 以3为头:321
7
入栈序列与出栈序列
若已知栈的输入序列为1 2 3 4,则输出序列有 多少种呢? 以1为头:1234 1243 1324 1342 1432 以2为头:2134 2143 2314 2341 2431 以3为头:3214 3241 3421 以4为头:4321 当输入序列为1 2 … n时,经过栈可获得的输 出序列的个数由尤.卡塔南数决定,即:
while(!IsEmpty(S))
{ Pop(&S,&x); printf(“%d”,x); } }
37
十进制数转换成K进制数
void Conversion(int N,int base)
{ Stack S; int x; InitStack(&S); /*S为顺序栈或链栈*/
while(N)
{ x=N%base; Push(&S, x); N=N/base; } while(!IsEmpty(S)) { Pop(&S,&x); if(x<10) printf(“%d”,x);
top[1]
27
两栈共享的数据结构定义
#define M 100 typedef struct
{
ElemType Stack[M];
int top[2];
} DqStack;
28
两栈共享的初始化
void InitStack ( DqStack *S )
{ S->top[0]=-1; S->top[1]=M; }
14
顺序栈的top指针
top==-1,表示栈空; top== stacksize-1,表示栈满; 每插入一元素时,top加1; 每删除一元素时,top减1;
15Leabharlann 顺序栈的操作过程示意栈满
5 top top top top top top F E 5 top top top top top top top F E D C B A 出栈 栈空 5 4 3 2 1 0
17
顺序栈的基本操作
顺序栈的初始化操作 顺序栈的判空操作 顺序栈的判满操作 顺序栈的插入操作(入栈) 顺序栈的删除操作(出栈) 顺序栈的读取栈顶元素操作
18
顺序栈的初始化
void InitStack ( SeqStack * s ) { S->top= -1; }
19
顺序栈的判空
23
顺序栈中读取栈顶元素
int GetTop ( SeqStack *s, ElemType *e ) { if ( S->top== -1 ) return FALSE; *e=S->elem[S->top]; return TRUE; }
24
两栈共享技术
若在一个程序中要同时使用多个栈,如果采用 顺序存储结构 会因为栈空间大小难以准确估计,产生有的栈 溢出,有的栈还很空闲的情况 解决措施:两栈共享技术
答案:D
10
栈的抽象数据类型定义
数据元素:
可以是任意类型的数据,但必须属于同一 个数据对象。
关系: 栈中数据元素之间是线性关系。 基本操作:
11
栈的基本操作
1. InitStack(S)
3. IsEmpty(S) 5. Push(S,x) 7. GetTop(S,x)
2. ClearStack(S)
top->next=temp;
return TRUE; }
/* 修改当前栈顶指针 */
34
链栈的出栈操作
int Pop(LinkStack top, ElemType *x) { temp=top->next; if(temp==NULL) return FALSE; /*栈为空*/ top->next=temp->next; *x=temp->data;
39
栈的应用2 — 括号匹配问题
如此反复,直到:
输入序列和栈同时变为空,说明所有括号完 全匹配;
输入序列已读尽,而栈中仍有等待匹配的左 括号,说明括号不匹配,表达式不合法; 或者读入了一个右括号,而栈中已无等待匹 配的左括号,同样属不合法的情况。
40
栈的应用3—回文游戏
顺读与逆读字符串一样(不含空格) 读入字符串 去掉空格(原串) 压入栈 原串字符与出栈字符依次比较 若不等,非回文 若直到栈空都相等,回文
ElemType
data;
struct node *next; }LinkStackNode, *LinkStack;
33
链栈的入栈操作
int Push(LinkStack top, ElemType x) { temp=( )malloc(sizeof(LinkStackNode)); if(!temp) return FALSE; temp->data=x; temp->next=top->next;
d a d
top
41
栈的应用4—表达式求值
中缀表达式 a*b+c a+b*c a+(b*c+d)/e 后缀表达式 ab*c+ abc*+ abc*d+e/+
42
中缀表达式求值
操作数栈和运算符栈
例 计算 2+4-3*6
4 + 2 操作数 运算符 18 6 操作数 运算符
43
6 操作数 运算符
6 3 * 6 操作数 运算符
25
两栈共享技术
主要利用了栈“栈底位置不变,而栈顶位置 动态变化”的特性。 首先为两个栈申请一个共享的一段存储空间 S[M] 然后将两个栈的栈底分别放在存储空间的两 端,分别是0,M-1。
26
共享栈的空间示意
top[0]和top[1]分别为两个栈顶指示器
Stack:0 M-1