数据结构-2004-02-03栈和队列
数据结构-栈与队列

栈 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。
数据结构栈和队列

实验二栈和队列一、实验目的1、掌握栈的特点(先进后出FILO)及基本操作,如入栈、出栈等,栈的顺序存储结构和链式存储结构,以便在实际问题背景下灵活应用。
2、掌握队列的特点(先进先出FIFO)及基本操作,如入队、出队等,队列顺序存储结构、链式存储结构和循环队列的实现,以便在实际问题背景下灵活应用。
二、实验内容1、顺序栈的实现和运算;2、循环队列的实现和运算;3、栈的运用—十进制转八进制运算。
三、实验要求1、学生用C++/C完成算法设计和程序设计并上机调试通过;2、撰写实验报告,提供实验测试数据和实验结果;3、分析算法,要求给出具体的算法分析结果,包括时间复杂度和空间复杂度,并简要给出算法设计小结和心得。
四、实验准备1、掌握栈和队列这两种抽象数据类型的特点,并能在相应的应用任务中正确选用它们;2、熟练掌握顺序栈和循环队列的基本操作实现算法,特别应注意栈满和栈空的条件以及它们的描述方法,循环队列中队满和队空的描述方法。
3、在学习顺序栈的基本操作实现算法时,应注意:在书上给出的结构定义是采用了一种动态管理方式(不够时,可以再分配),但在C 语言中,用数组来存储顺序栈,是静态分配,即不能随机分配空间,这点易引起大家的误解。
五、实验步骤1、编程实现顺序栈的各种基本运算,并在此基础上设计一个主程序,完成如下功能:(1)初始化顺序栈;(2)给定一个元素,将此元素压入此栈中;(3)将栈顶一个元素弹出此栈。
2、编写一个程序实现循环队列的各种基本运算,并在此基础上设计一个主程序,完成如下功能:(1)初始化循环队列;(2)给定一个元素,将此元素插入此队列中;(3)将队头一个元素出队。
3、栈的运用实例十进制转八进制。
六、实验参考代码1、顺序栈的实现和运算;#include <stdio.h>#include <stdlib.h>#define OK 1#define ERROR 0#define OVERFLOW -2typedef int ElemType;typedef int Status;//----- 栈的顺序存储表示-----#define STACK_INIT_SIZE 100 // 存储空间的初始分配量#define STACKINCREMENT 10 // 存储空间的分配增量typedef struct {ElemType *base;ElemType *top;int stacksize;} SqStack;// 构造一个空栈SStatus InitStack(SqStack &S){S.base = (ElemType *)malloc(STACK_INIT_SIZE * sizeof(ElemType));if(!S.base) exit (OVERFLOW);S.top = S.base;S.stacksize = STACK_INIT_SIZE;return OK;}// 判栈S是否为空栈Status StackEmpty(SqStack S){if (S.top==S.base) return OK;else return ERROR;}//入栈函数Status Push (SqStack &S, ElemType e) {if(S.top - S.base >= S.stacksize){S.base=(ElemType*)realloc(S.base,(S.stacksize+STACKINCREMENT)* sizeof(ElemType)); if(!S.base) exit (OVERFLOW);S.top = S.base + S.stacksize;S.stacksize += STACKINCREMENT;}* S.top++ = e;return OK;}//出栈函数Status Pop (SqStack &S, ElemType &e) {if(S.top == S.base) return ERROR;e = * --S.top;return OK;}//输出顺序栈函数void OutStack(SqStack S){ int *p;if(S.top == S.base){printf("这是一个空栈!");}elsefor(p= S.top-1; p>= S.base;p--)printf("%6d", *p);printf("\n");}//主函数void main(){ SqStack s;int cord; ElemType a;printf("第一次使用必须初始化!\n");do{printf("\n 主菜单\n");printf(" 1 初始化顺序栈");printf(" 2 插入一个元素");printf(" 3 删除栈顶元素");printf(" 4 结束程序运行");printf("\n------------------------------------------------------------------------------\n"); printf("请输入您的选择( 1, 2, 3, 4)");scanf("%d",&cord);printf("\n");switch(cord){ case 1:InitStack(s);OutStack(s);break;case 2:printf("请输入要插入的数据元素:a=");scanf("%d",&a);Push(s,a);printf("%d 进栈之后的栈:",a);OutStack(s);break;case 3:Pop(s,a);printf("栈顶元素%d 出栈之后的栈:",a);OutStack(s);break;case 4:exit(0);}}while (cord<=4);}2、循环队列的实现和运算;#include <stdio.h>#include <stdlib.h>#define OK 1#define ERROR 0#define OVERFLOW -2typedef int QElemType;typedef int Status;//----- 队列的顺序存储表示-----#define MAXQSIZE 100 // 存储空间的初始分配量typedef struct {QElemType *base;int front;int rear;} SqQueue;// 构造一个空队列QStatus InitQueue(SqQueue &Q){Q.base=(QElemType*)malloc(MAXQSIZE*sizeof(QElemType)); if(!Q.base)exit(OVERFLOW);Q.front=Q.rear=0;return OK;}//判队列是否为空Status QueueEmpty (SqQueue Q) {if(Q.rear==Q.front) return OK;else return ERROR ;}//入队函数Status EnQueue (SqQueue &Q, QElemType e) {if((Q.rear+1)%MAXQSIZE==Q.front) return ERROR;Q.base[Q.rear]=e;Q.rear=(Q.rear+1)%MAXQSIZE;return OK;}//出队函数Status DeQueue (SqQueue &Q, QElemType &e) {if(Q.rear==Q.front) return ERROR;e=Q.base[Q.front];Q.front=(Q.front+1)%MAXQSIZE;return OK;}//输出循环队列函数void OutQueue(SqQueue Q)if(Q.front == Q.rear){printf("这是一个空队列!");}else{n= (Q.rear- Q.front+ MAXQSIZE) % MAXQSIZE;i= 1;while ( i<= n){printf("%6d", Q.base[(Q.front+i-1)% MAXQSIZE] );i++;}printf("\n");}}//主函数void main(){ SqQueue q;int cord; QElemType a;printf("第一次使用必须初始化!\n");do{printf("\n 主菜单\n");printf(" 1 初始化循环队列");printf(" 2 进队一个元素");printf(" 3 出队一个元素");printf(" 4 结束程序运行");printf("\n------------------------------------------------------------------------------\n"); printf("请输入您的选择( 1, 2, 3, 4)");scanf("%d",&cord);printf("\n");switch(cord){ case 1:InitQueue(q); //调用初始化算法;OutQueue(q);break;case 2:printf("请输入要插入的数据元素:a=");scanf("%d",&a);EnQueue (q, a); //调用进队算法;printf("%d 进队之后的队列:",a);OutQueue(q);break;case 3:DeQueue (q, a); //调用出队算法;printf("队头元素%d 出队之后的队列:",a);OutQueue(q);break;exit(0);}}while (cord<=4);}3、栈的应用—十进制转八进制#include <stdio.h>#include <stdlib.h>#define OK 1#define ERROR 0#define OVERFLOW -2typedef int ElemType;typedef int Status;#define STACK_INIT_SIZE 100#define STACKINCREMENT 10typedef struct {ElemType *base;ElemType *top;int stacksize;} SqStack;// 构造一个空栈SStatus InitStack(SqStack &S){S.base = (ElemType *)malloc(STACK_INIT_SIZE * sizeof(ElemType));if(!S.base) exit (OVERFLOW);S.top = S.base;S.stacksize = STACK_INIT_SIZE;return OK;}// 判栈S是否为空栈Status StackEmpty(SqStack S){if (S.top==S.base) return OK;else return ERROR;}//入栈函数Status Push (SqStack &S, ElemType e) {if(S.top - S.base >= S.stacksize){S.base=(ElemType*)realloc(S.base,(S.stacksize+STACKINCREMENT)* sizeof(ElemType)); if(!S.base) exit (OVERFLOW);S.top = S.base + S.stacksize;S.stacksize += STACKINCREMENT;}* S.top++ = e;return OK;}//出栈函数Status Pop (SqStack &S, ElemType &e) {if(S.top == S.base) return ERROR;e = * --S.top;return OK;}//十进制转八进制函数void conversion(){ SqStack S;int n,e;InitStack(S);printf("请输入一个十进制数:");scanf("%d",&n);while(n){Push(S,n%8);n=n/8;}printf("转换之后的八进制数为:");while(!StackEmpty(S)){Pop(S, e);printf("%d",e);}printf("\n");}void main(){conversion();}(注:文档可能无法思考全面,请浏览后下载,供参考。
《数据结构栈和队列》课件

网络通信
在网络通信中,数据包按 照到达顺序进入队列,等 待处理。
打印任务管理
打印任务按照到达顺序进 入队列,等待打印机的空 闲时间进行处理。
05
栈与队列的比较
结构比较
栈和队列是两种不同的数据结构,它们在结构上有明显的区 别。
课程目标
掌握栈和队列的基本 概念、原理和应用场 景;
能够运用栈和队列解 决实际问题和算法设 计。
理解栈和队列在解决 实际问题中的作用和 优势;
02
数据结构概述
数据结构定义
数据结构定义
数据结构是数据元素之间相互关系和数据元素属性的 抽象表示。
数据结构组成
数据元素、数据元素之间的关系和数据元素的属性。
表达式求值:例如,括号内的运算优先级高于括号外的运算,可以使用栈来保存括 号和运算符,以便正确地计算表达式的值。
深度优先搜索(DFS):在图的遍历中,可以使用栈来保存待访问的节点,实现深 度优先搜索。
04
队列(Queue)
队列的定义
01
队列是一种先进先出(FIFO)的数据结构,用于存储元素的集 合。
07
总结与展望
本章总结
栈和队列是两种常见的数据结构,具有特定的操作规则和特性。
通过学习栈和队列,我们掌握了先进先出(FIFO)和后进先出(LIFO)的 原理,以及如何在程序中实现这些数据结构。
本章还介绍了栈和队列在实际问题中的应用,如括号匹配、表达式求值等 。
数据结构的发展趋势与未来展望
01
随着计算机技术的不断发展,数据结构也在不断演进
02
队列中的元素遵循先入队后出队的规则,即最早进入队列的元
数据结构栈和队列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
数据结构课件——栈和队列

3
D,E,F,G,H进队 进
2 front
规则:
队头指针进1: 队头指针进1: front = (front+1) % size; size; 队尾指针进1: size; 队尾指针进1: rear = (rear+1) % size; 队列初始化: 队列初始化:front = rear = 0; 队空条件: rear; 队空条件:front == rear; 队满条件: 队满条件:(rear+1) % size == front
队列的抽象数据类型
class Queue { public: Queue ( const int =list_size ); //构造函数 ~ Queue(); //析构函数 void enqueue ( const ELEM&); //进队 ELEM dequeue ( ); //出队列 ELEM firstValue( )const; //取队头元素值 void clear ( ); //置空队列 bool isEmpty ( ) const ; //判队列空否 }
队列的进队和出队
A
front rear 空队列 front rear A进队
A B
front rear B进队
A B C D
front rear C, D进队
B C D
front rear A退队
C D
front rear B退队
C D E F G
front rear E,F,G进队 进
C D E F G
top 空栈 top d c b a d 进栈
top top
a a 进栈
top top
b a b 进栈
top d c b a e 进栈溢出 top d c b a d退栈
数据结构栈和队列

数据结构03栈与队列通常称,栈与队列是限定插入与删除只能在表地"端点"进行地线性表。
线性表栈(表尾)队列(队尾)Insert(L,i,x)Insert(S,n+1,x)Insert(Q,n+1,x)1≤i≤n+1Delete(L,i)Delete(S,n)Delete(Q,1)1≤i≤n栈与队列是两种常用地数据类型3.1 栈地基本概念3.2 栈地顺序存储结构与实现3.3 栈地链式存储结构与实现3.4 队列地基本概念3.5 队列地顺序存储3.6 队列地链式存储先入后出同点?后入先出栈(Stack)是限定仅在表尾进行插入或删除地线性表。
允许插入与删除地一端叫做栈顶(Top),另一端叫做栈底(Base)。
当栈没有任何元素时则称为空栈。
假设栈S=(a1,a2,a3,…an),则a1称为栈底元素,an为栈顶元素。
栈元素按a1,a2,a3,…an地次序进栈,弹栈地第一个元素应为栈顶元素。
因此,栈地修改是按后进先出地原则进行地,所以,栈称为后进先出LIFO。
栈地抽象数据类型定义为:ADT Stack{数据对象:D={ai|ai∈ElemSet,i=1,2,…,n,n≥0}数据关系:R={<ai-1,ai>|ai-1,ai∈D,i=2,…,n}约定an端为栈顶,a1端为栈底基本操作:}ADT StackInitStack(&S)初始条件:无操作结果:构造一个空栈S DestoryStack(&S)初始条件:栈S已存在操作结果:栈S被销毁CleanStack(&S)初始条件:栈S已存在操作结果:栈S清为空栈StackEmpty(S)初始条件:栈S已存在操作结果:若栈S为空栈,则返回TRUE,否则FALSE StackLength(S)初始条件:栈S已存在操作结果:返回S地元素个数,即栈地长度GetTop(S,&e)初始条件:栈S已存在且非空操作结果:用e返回S地栈顶元素… …a1a2anPush(&S,e)初始条件:栈S已存在操作结果:插入元素e为新地栈顶元素… …a1a2an ean Pop(&S,&e)初始条件:栈S 已存在且非空操作结果:删除S 地栈顶元素,并用e 返回其值a1a2an-1… …e=anStackTraverse(S,visit())初始条件:栈S已存在且非空操作结果:从栈顶到栈底依次对S地每个元素调用函数visit()。
《栈和队列》课件
栈与队列的区别
数据存储方式
栈是后进先出(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
应用场景
《数据结构课件、代码》第3章栈和队列
栈也可以通过链表实现,其中链表的 头部作为栈顶。
在Java中,可以使用`java.util.Stack` 类实现栈,该类继承自`Vector`类, 提供了丰富的操作方法来管理栈。
总结词
应用场景不同
详细描述
栈常用于实现函数调用、括号匹配等后进 先出的操作。而队列常用于实现任务调度 、缓冲区处理等先进先出的操作。
THANKS
感谢观看
04
栈和队列的算法复杂度分 析
算法时间复杂度分析
栈的常见操作包括push、pop和peek等,其中push和pop操 作的时间复杂度为O(1),而peek操作的时间复杂度也为O(1)。
队列的常见操作包括enqueue、dequeue和peek等,其中 enqueue操作的时间复杂度为O(1),dequeue操作的时间复杂 度为O(n),n为队列中元素的个数,peek操作的时间复杂度为 O(1)。
算法空间复杂度分析
栈的空间复杂度主要取决于其存储方 式,如果使用数组实现,则空间复杂 度为O(n),n为栈中元素的个数;如 果使用链表实现,则空间复杂度为 O(1)。
队列的空间复杂度也取决于其存储方式, 如果使用数组实现,则空间复杂度为 O(n),n为队列中元素的个数;如果使 用链表实现,则空间复杂度为O(1)。
《数据结构课件、代 码》第3章栈和队列
目录
• 栈(Stack) • 队列(Queue) • 栈与队列的应用 • 栈和队列的算法复杂度分析 • 数据结构中的栈和队列与其他数据结构的比较
01
栈(Stack)
栈的定义
01
数据结构-2004-02-03栈和队列
溢出
上溢 — 当堆栈已满时做插入操作. (top=M) 下溢 — 当堆栈为空时做删除操作. (top=0)
二. 进栈(PUSH)算法
0 M-1
a b
c
d
item
…
top
int PUSH( char STACK[ ], int top, char item ) { if (top==M) { printf( ―Stack is full !‖ ); return(false); } else { top=top+1;
插入
先进先出
ቤተ መጻሕፍቲ ባይዱ
二. 队列的基本操作
1. 队列的插入 ADDQ(Q, item) 2. 队列的删除 DELQ(Q) 3. 测试队列是否为空 EMPTY(Q) 4. 检索当前队头元素 FRONTQ(Q) 5. 创建一个空队 CREATQ(Q)
3.1 堆栈的基本概念及其操作
0. 背景
1 括号匹配问题 (()((()))()(()((()) 2 表达式计算问题 A+B *C/D–E /F
3.1 堆栈的基本概念及其操作
(()((()))()(()((())
( (
3.1 堆栈的基本概念及其操作
A+B *C/D–E /F
F D C B B*C/D B*C E/F E A+B*C/D-E/F A+B*C/D A
3.3 堆栈的链式存储结构
一. 构造原理
链接堆栈就是用一个线性链表来实现 一个堆栈结构, 同时设置一个指针变量(top) 指出当前栈顶元素所在链结点的位置。当 栈为空时,有top=Null。
在一个初始为空的链接堆栈中依次插入数据元素 A, B, C, D 以后, 堆栈的状态为
数据结构课件第3篇章栈和队列
循环队列实现原理
01
循环队列定义
将一维数组看作首尾相接的环形结构,通过两个指针(队头和队尾指针)
在数组中循环移动来实现队列的操作。当队尾指针到达数组末端时,再
回到数组起始位置,形成循环。
02
判空与判满条件
在循环队列中,设置一个标志位来区分队列为空还是已满。当队头指针
等于队尾指针时,认为队列为空;当队尾指针加1等于队头指针时,认
栈在函数调用中应用
函数调用栈
在程序执行过程中,每当发生函数调用时,系统会将当前函数的执行上下文压入一个专门的栈中,称为函数调用 栈。该栈用于保存函数的局部变量、返回地址等信息。当函数执行完毕后,系统会从函数调用栈中弹出相应的执 行上下文,并恢复上一个函数的执行状态。
递归调用实现
递归调用是一种特殊的函数调用方式,它通过在函数调用栈中反复压入和弹出同一函数的执行上下文来实现对问 题的分解和求解。在递归调用过程中,系统会根据递归深度动态地分配和管理函数调用栈的空间资源。
栈和队列的应用
栈和队列在计算机科学中有着广泛的应用,如函数调用栈、表达式求 值、缓冲区管理等。
常见误区澄清说明
误区一
栈和队列的混淆。虽然栈和队列都是线性数据结构,但它们的操作方式和应用场景是不同的。栈是后进先出,而队列 是先进先出。
误区二
认为栈和队列只能通过数组实现。实际上,栈和队列可以通过多种数据结构实现,如链表、循环数组等。具体实现方 式取决于应用场景和需求。
后缀表达式求值
利用栈可以方便地实现后缀表达式的求值。具体步骤 为:从左到右扫描表达式,遇到数字则入栈,遇到运 算符则从栈中弹出所需的操作数进行计算,并将结果 入栈,最终栈中剩下的元素即为表达式的结果。
中缀表达式转换为后缀表达式
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
3.7 队列的链式存储结构
一. 构造原理
队列的链式存储结构是用一个线性链表表 示一个队列, 指针 front 与rear 分别指向队头 元素与队尾元素所在的链结点。
struct queue_node { char data; struct queue_node *link; } struct queue_node *front, *rear;
约 定:
rear 指向当前队尾元素所在的位置, front 指向当前队头元素所在位置的前一个位置.
QUEUE[ M]
0
M-1
b c d
front rear
初始时, 队列为空, 有 front=-1 rear=-1 测试队列为空的条件是 front==rear
二. 进队算法
0 M-1
a b c d
数据结构
第一章 绪 论 第二章 线 性 表 第三章 栈和队列 第四章 串和数组 第五章 二叉树和树 第六章 图和广义表
第七章 排
第八章 查
序
找
第九章 文
件
第三章 栈和队列
3.1 栈的概念及其操作 1 堆栈的顺序存储结构 2 堆栈的链式存储结构 3.2 堆栈的应用举例 3.3 队列的基本概念及其操作 1 队列的顺序存储结构 2 队列的链式存储结构 3.4 队列的应用举例
front=front->link; if (front==Null) rear=Null;
ch=p->data;
free(p); } }
0 M-1
a b c d
front rear
char DELQ( char QUEUE[ ], int front, int rear) { if (front==rear) printf( ―Queue is empty!‖ ); else { front++; return(QUEUE[front]); } }
front=(front+1)%M
循环队列为空的条件:
rear==front
进队算法
int ADQ( char QUEUE[ ], int front, int rear,char x) { if ((rear+1)%M==front) { printf( ―Queue is full!‖ ); return(FALSE); else { rear=(rear+1)%M; QUEUE[rear]=x; return(TRUE); } }
3.4 栈的应用举例
1、设计一算法:判断一个算术表达式的圆括号是否 正确配对 例如: 100*(7+2*(4-1))
# define maxsize 100 int express() { char exp[maxsize]; char STACK[maxsize]; printf(―Please input the exp:\n‖); scanf(―%s‖,exp); top=-1; i=0; while(exp[i]!=‗\0‘) { if (exp[i]==‗(‘) PUSH( STACK, top, ‗(‗ ); if (exp[i]==‗)‘) if (pop( STACK, top )!=‗(‘) return(false); i++; } if(top!=-1) return(false); return(true);
top
e
二. 堆栈的基本操作
1. 2. 3. 4. 插入 PUSH(S,item) 删除 POP(S) 测试堆栈是否为空 EMPTY(S) 检索当前栈顶元素 TOP(S)
特殊性:
1. 其操作仅仅是一般线性表的操作的一个子集。 2. 插入和删除操作的位置受到限制。
3.2 堆栈的顺序存储结构
一. 构造原理
描述堆栈的顺序存储结构最简单的方法是利用一 维数组 STACK[ M ] 来表示, 同时定义一个整型变量 ( 不妨取名为 top ) 给出栈顶元素的位置.
STACK[M]
0 1 2 3 …… M-1
a b c d e
top=5
栈的定义:
#define M 1024; char STACK[M]; int top;
插入
先进先出
二. 队列的基本操作
1. 队列的插入 ADDQ(Q, item) 2. 队列的删除 DELQ(Q) 3. 测试队列是否为空 EMPTY(Q) 4. 检索当前队头元素 FRONTQ(Q) 5. 创建一个空队 CREATQ(Q)
特殊性:
1. 其操作仅仅是一般线性表的操作的一个子集。 2. 插入和删除操作的位置受到限制。
存在的问题
假溢出问题:
0 M-1
front
rear
四. 循环队列
把队列(数组)设想成头尾相连的循环表,使得 数组前部由于删除操作而导致的无用空间尽可能 得到重复利用,这样的队列称为循环队列。
M-2 M-1
0 0 1 2 3 4 ……
M-2 M-1
1
……
进队操作:rear=(rear+1)%M
: :
front rear
item
void ADDQ( char QUEUE[ ], int rear, char item ) { if (rear==M-1) printf( ―Queue is full!‖ ); else {
rear=rear+1;
QUEUE[rear]=item;
}
}
三. 出队算法
struct queue_node * rear, char item ) { p=(struct queue_node *)malloc(sizeof(struct queue_node )); // 申请一个链结点 // p->data=item; p->link=Null; if (rear ==Null) { rear=p; // 插入空队的情况 // front=rear; } else { p->link=rear; rear=p; // 插入非空队的情况 // } }
3 4
2
出队操作:front=(front+1)%M
约 定:
rear 指向当前队尾元素所在的位置, front 指向当前队头元素所在位置的前一个位置.
进队操作:rear=(rear+1)%M
rear=(rear+1)%M 循环队列满的条件是 (rear+1)%M==front
(始终有一个空元素)
出队操作:front=(front+1)%M
在一个初始为空的链接队列中依次插入数据元素 A, B, C, D 以后, 队列的状态为
front
rear
A
B
C
D
^
空队对应的链表为空链表,空队的标志是 rear= = Null
二. 入队算法
front
rear
…
item
^
p
算法:
void ADD_QUEUE( struct queue_node *front,
STACK[top]=item;
} } return(true);
三. 退栈(POP)算法
0 M-1
a b
c
d e
top
…
char POP( char STACK[ ], int top) { if (top == -1) printf( ―Stack is empty !‖ ); else { ch=STACK[top]; } } top=top –1; return(ch);
溢出
上溢 — 当堆栈已满时做插入操作. (top=M) 下溢 — 当堆栈为空时做删除操作. (top=0)
二. 进栈(PUSH)算法
0 M-1
a b
c
d
item
…
top
int PUSH( char STACK[ ], int top, char item ) { if (top==M) { printf( ―Stack is full !‖ ); return(false); } else { top=top+1;
3.3 堆栈的链式存储结构
一. 构造原理
链接堆栈就是用一个线性链表来实现 一个堆栈结构, 同时设置一个指针变量(top) 指出当前栈顶元素所在链结点的位置。当 栈为空时,有top=Null。
在一个初始为空的链接堆栈中依次插入数据元素 A, B, C, D 以后, 堆栈的状态为
top
栈顶
D C B
三. 退栈(pop)算法
top
item
......
^
P
char POP_STACK( struct stack_node *top ) { if (top == Null) printf( ―Stack is empty!‖ ); else { p=top; //暂时保存栈顶结点的地址// ch=top->data(top); //保存被删栈顶的数据信息// top=top->link; //删去栈顶结点// free(p); //释放被删结点// return(ch); }
三. 出队算法
front
rear
…
^
char DEL_QUEUE(struct queue_node * front, struct queue_node * rear) { if (front== Null) printf( ―Queue is empty!‖ ); else
{ p=front;
3.5 队列的基本概念及其操作
一. 队列的定义
队列简称队,是一种只允许在表的一端进行插 入操作, 而在表的另一端进行删除操作的线性表。为队头, 队头元素的位置 由front指出。