数据结构课件第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章 栈和队列

栈满 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课件

栈的运用 例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
《栈和队列》课件

栈与队列的区别
数据存储方式
栈是后进先出(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
数据结构课件第3篇章栈和队列

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

*x)
{ StackNode *p; if (top= =NULL) return NULL;
else { *x = top->data;
p = top; top = top->next; free (p); return top; } }
3.2 栈的应用举例
例 3.1 简单应用:数制转换问题
将十进制数N转换为r进制的数,其转换方法利用辗转相除法: 以N=3467,r=8为例转换方法如下:
N 3467 433 N / 8 (整除) N % 8(求余) 433 54 3 1 低
54
6
6
0
6
6 高
所以:(3467)10 =(6613)8
我们看到所转换的8进制数按低位到高位的顺序产生 的,而通常的输出是从高位到低位的,恰好与计算过程 相反,因此转换过程中每得到一位8进制数则进栈保存, 转换完毕后依次出栈则正好是转换结果。
基本操作算法: ⑴ 置空栈:首先建立栈空间,然后初始化栈顶指针。 SeqStack *Init_SeqStack()
{ SeqStack *s;
s=malloc(sizeof(SeqStack)); s->top= -1; return s; } ⑵ 判空栈
int Empty_SeqStack(SeqStack *s)
第3章 栈和队列
本章主要介绍以下内容:
栈的概念、存储结构及其基本操作
队列的概念、存储结构及其基本操作 栈与队列的应用举例
退出
3.1 栈
3.2 栈的应用举例 3.3 队列
3.4 队列的应用举例
3.1 栈
3.1.1 栈的定义
栈是一种特殊的线性表。其特殊性在于限定插入 和删除数据元素的操作只能在线性表的一端进行。如 下所示: a1, a2, a3, ..., an 插入和删除端
数据结构第03章栈和队列.ppt

插入元素到栈顶(即表尾)的操作,称为入栈。 从栈顶(即表尾)删除最后一个元素的操作,称为出栈。
强调:插入和删除都只能在表的一端(栈顶)进行!
6
栈的抽象数据类型
ADT Stack{ 数 据 对 象 : D={ai | ai ElemSet , i=1 , 2,... ,n,n>=0} 数据关系: R={<ai-1 , ai >| ai-1 , ai D , i=2,...,n} 基本操作: 栈初始化:StackInit() 判栈空:StackEmpty(S) 入栈:Push(S,x) 出栈:Pop(S)
较好的做法是,设立一个输入缓冲区,用以 接受用户输入的一行字符,然后逐行存入用户数 据区。允许用户输入出错,并在发现有误时可以 及时更正。
29
可以把输入缓冲区设为一个栈结构,每当 从终端接受了一个字符后先作如下判别:如果 它既不是退格符也不是退行符,则将该字符压 入栈顶;如果是一个退格符,则从栈顶删去一 个字符;如果是一个退行符,则将字符栈清空 为空栈。
19
顺序栈基本操作--初始化
SqStack InitStack(SqStack &S) {//构造一个空栈S S.base=(SElemtype *)malloc (STACK_INIT_SIZE)*sizeof(SElemtype); if(!S.base) exit(OVERFLOW); S.top=s.base; S.stackzise=STACK_INIT_SIZE; return OK; }
] 6
) 7
] 8
可能出现的不匹配的情况: 1.到来的右括弧不是所“期待”的; 2.到来的是“不速之客”(左括号); 3.直到结束,也没有到来所“期待”的;
数据结构经典课件 第3章 栈与队列

1第3章栈和队列3.1 栈3.2 队列2栈和队列是两种特殊的线性表,其特殊性在于插入和删除运算的限制上。
这两种线性结构在程序设计中经常使用。
33.1 栈3.1.1 栈的抽象数据类型3.1.2 顺序栈3.1.3 链式栈3.1.4 栈的应用举例3.1.5 栈与递归43.1 栈(stack)栈是一种限定仅在一端进行插入和删除操作的线性表。
插入:入栈(压栈) 删除:出栈(退栈) 插入、删除一端被称为栈顶(浮动),另一端称为栈底(固定)。
特征:后进先出(LIFO表,Last-In First-Out)。
k 0k 1k 2k 3栈底栈顶出栈入栈53.1.1 栈的抽象数据类型template <class ELEM> class Stack {public:void clear(); // 清空bool push(const T item); // 入栈bool pop(T& item); // 出栈bool top(T& item); // 返回栈顶内容bool is Empty(); //判栈是否空bool isFull(); // 判栈是否满};6栈的实现顺序栈采用顺序存储结构表示的栈链式栈采用链式存储结构表示的栈7template <class T>class arrStack : public Stack<T> {private:int mSize; // 栈容量int top; // 栈顶指针,初始为-1T *st; // 存放栈内容的连续空间public:arrStack(int size) { mSize=size; top=-1; st=new T[mSize];}arrStack() {mSize = 0; top = -1; st = null;}~arrStack() { delete[] st; }void clear() { top = -1;}bool push(const T item);bool pop(T& item);bool top(T& item);};3.1.2 顺序栈8template <class T>bool arrStack<T>::push(const T item) {if (top==mSize-1){cout<<"栈满"<endl;return false;}else {st[++top]=item;return true;}}k 0k 1k 2k 3top top栈空9自动解决栈溢出的入栈操作template <class T>bool arrStack<T>::push(const T item) {if (top==mSize-1){ // 扩展存储空间T * new2St = new T[mSize*2];for (i=0;i<top ;i++) newst[i]=st[i];delete [] st;st=newSt;mSize *=2;}st[++top]=item;return true;}10template <class T>bool arrStack<T>::pop(T& item) {if (top==-1){cout<<“栈为空,不能执行出栈操作"<endl;return false;}else {item = st[top--];return true;}}11template <class T>bool arrStack<T>::top(T& item) {if (top==-1){cout<<“栈为空,不能读取栈顶元素"<endl;return false;}else {item = st[top ];return true;}}123.1.3 链式栈\top13template <class T>class lnkStack : public Stack<T>{private:Link<T>*top; // 头指针int size; // 结点个数public:lnkStack(int defSize) { top=NULL; size=0; }~lnkStack() { clear(); }void clear();bool push(const T item);bool pop(T& item);bool top(T& item);};14template <class T>void lnkStack::clear(){while (top!=NULL) {Link<T>* temp = top;top = top->next;delete temp;}size=0;}template <class T>bool lnkStack::push(const T item){Link<T>* tmp=new Link<T >(item, top );top=tmp;size++;return true;}template <class T>bool lnkStack::pop(T& item) {Link<T>* item;if (size==0){cout<<"栈空"<<endl;return false;}item=top->data;tmp=top->next;delete top;top=tmp;size--;return true;}153.1.4 栈的应用举例数制转换 迷宫问题表达式括号匹配检验 表达式求值 背包问题161.数制转换(1348)10=(2504)8==========================N N/8 N%81348 168 416821 021 2 52 0 2while (N) {N%8入栈;N/8=>N;}while (栈非空){出栈;输出;}17//将非负十进制整数转换成八进制输出void conversion( ){Stack s;cin>>N;while (N){s.push( N%8); N=N/8;}while (!s.isEmpty()){s.pop(e); cout<<e;}}182.迷宫问题1234567891011121314151617181213141516171819201419*1234o o o o oo o o o o o oo o o o o o入口出口20*1234入口出口0 1 2 3 4 5 6 7 8 9 10 1112345687109OO21算法基本思路“穷举求解”,即从入口出发,沿某一方向向前试探,若能走通,则继续往前走;否则原路退回,换一个方向再继续试探,直到走到出口或确定无路可走为止。
chapter03栈和队列课件PPT

队列为空:判断队列是 否为空,返回一个布尔 值。
队列满:判断队列是否 已满,返回一个布尔值。
队列的性质和应用
队列的性质
队列具有先进先出的特性,即最早进 入队列的元素将最先被删除。
队列的应用
队列在计算机科学中被广泛应用于各 种场景,如任务调度、缓冲处理、事 件处理等。
04
栈和队列的比较与选择
栈和队列的异同点
相同点 都是线性数据结构
都有后进先出(LIFO)的特性
栈和队列的异同点
01
不同点
02
栈只允许在固定的一端(称为栈顶)进行插入和删除操作,而队列允 许在两端进行操作。
03
栈中的元素必须按照先进后出的顺序进行操作,而队列中的元素则按 照先进先出的顺序进行操作。
04
栈主要用于实现递归、括号匹配等算法,而队列主要用于实现生产者 消费者模型、打印机的打印队列等应用。
课件:Chapter03栈和队列
• 引言 • 栈的概念和操作 • 队列的概念和操作 • 栈和队列的比较与选择 • 总结与回顾
01
引言
主题简介
栈和队列是两种常见的数据结构,在 计算机科学和编程中有着广泛的应用。
队列是一种先进先出(FIFO)的数据 结构,用于存储元素的集合,其中新 元素总是添加到队列尾部,而删除操 作总是在队列头部进行。
展望
后续课程将介绍更多数据结构和算法,如链表、树、图等, 这些数据结构在计算机科学中有着广泛的应用。建议学生提 前预习相关内容,为后续课程打下坚实的基础。
THANKS
感谢观看
栈是一种后进先出(LIFO)的数据结 构,用于存储元素的集合,其中新元 素总是添加到栈顶,而删除操作总是 在栈顶进行。
课程目标和意义
【数据结构课件】栈和队列

top[1]
返回主目录
两栈共享的数据结构定义
#define M 100 typedef struct { StackElementType Stack[M]; StackElementType top[2]; /*top[0]和 top[1] 分别为两个栈顶指示器*/ }DqStack;
返回主目录
顺序栈中的进栈和出栈图例
top
E D
C B
top
B
top
A
A
A
返回主目录
top
顺序栈基本操作的实现
1)初始化
void InitStack(SeqStack *S)
{/*构造一个空栈S*/ S->top= -1;
}
返回主目录
2)判栈空
int IsEmpty(SeqStack *S)
/*判栈S为空栈时返回值为真,反之为假*/
返回主目录
进栈、出栈图例
根据栈定义,每次进栈的元素都被放在原 栈顶元素之上而成为新的栈顶,而每次出栈的 总是当前栈中“最新”的元素,即最后进栈的 元素。因此,栈又称为后进先出的线性表。简 称为LIFO表。如下图所示:
出栈 栈顶 进栈 出栈 进栈
an a2 a1
返回主目录
栈底
栈的抽象数据类型定义
数据元素:可以是任意类型的数据,但必须属于同 一个数据对象。 关系:栈中数据元素之间是线性关系 基本操作:
*x=S->Stack[S->top[1]];S->top[1]++;break; default: return(FALSE);
}
return(TRUE);
}
返回主目录
2. 链栈
教学课件第三章栈和队列

A( ){ …
B( ) { …
C( ) { …
A( ) ;
C( );
B( );
… }
… }
… }
A 直接调用自己
B间接调用自己
递归算法的编写 1)将问题用递归的方式描述(定义) 2)根据问题的递归描述(定义)编写递归算法
问题的递归描述(定义) 递归定义包括两项 基本项(终止项):描述递归终止时问题的求解; 递归项:将问题分解为与原问题性质相同,但规模较小 的问题;
}
top
f(1) 1
f(1)=1
f(2) 2*f(1) f(2)=2*f(1)
f(3) 3*f(2) f(3)=3*f(2)
f(4) 4*f(3) f(4)=4*f(3)
f(5) 5*f(4) f(5)=5*f(4)
例2 递归的执行情况分析
void print(int w) { int i;
if ( w!=0) { print(w-1);
(LIFO)。
a2
栈的特点
a1
后进先出(LIFO)
栈的示意图
栈在函数嵌套调用中的应用:
主函数 a 函数
b 函数
c 函数
r
s
t
函数的嵌套调用与返回
t
s
s
s
r
r
r
r
r
(a) 调用a函数, r进栈 (c) 调用c函数,t进栈 (e) 返回a函数,s退栈 (b) 调用b函数,s进栈 (d) 返回b函数,t退栈 (f) 返回主程序,r退栈
1
m
栈1底
栈1顶
栈2顶
栈2底
常采用将两个栈底设在可用空间的两端。
仅当两个栈顶相遇时,才产生上溢,即所有可用空间已用完。对 每个栈可用的最大空间就可能大于整个可用空间的一半m/2。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
算法(续): case ‘]’:{if(! Empty(s)&&GetTop(s)=‘[‘ ) pop(s,e); else state=0;break; }
}//switch ch=*exp++; }//while
if(state &&Empty(s)) return TRUE;
else return FALSE;
第3章 栈和队列
本章的基本内容是:
3.1 栈 3.2 栈的应用 3.3 队列 3.4 队列的应用
3.1 栈
问题1:在非常拥挤的情况下,汽车司机 应该如何组织人们上、下车?(假设通勤 车只有一个门)
如果编程模拟通勤车上下车情形,就要使 用某种后进先出的数据结构,而具有这种 属性的数据结构就是栈。
事实上,所有只有一个开口的容器都可以 看做是一个后进先出或先进后出的机构, 如井、陷阱、坑、瓶子等。
3.2 栈的应用
应用1:乘坐校园通勤车
本应用模拟问题1:先上车的人最后下来。每个 乘客用一个编号来表示,用户输入的乘客编号顺 序就是乘客的等车顺序,程序就是倒着输出这一 串编号,即乘客的下车顺序。
下面是乘客上/下车的主程序:
int main(){ //输入:用户提供数值n,代表n个乘客和n个乘客的编号 //输出:将乘客的编号倒着输出出来
可能是出栈次序有abc、acb、bac、bca、cba五种。
栈的顺序存储结构及实现
顺序栈——栈的顺序存储结构
如何改造数组实现栈的顺序存储?
012 3 4 56 78
a1
top 确定用数组的哪一端表示栈底。 附设指针top指示栈顶元素在数组中的位置。
栈的顺序存储结构及实现
012 3 4 56 7 8
return 0;
}
运行结果:
应用3:阶乘计算
n!=
1
当 n=1 时
n * ( n - 1)! 当 n≥1 时
递归的基本思想:
把一个不能或不好解决的大问题转化为一个或几 个小问题,再把这些小问题进一步分解成更小的 小问题,直至每个小问题都可以直接解决。
递归的要素:
⑴ 递归边界条件:确定递归到何时终止,也称 为递归出口; ⑵ 递归模式:大问题是如何分解为小问题的, 也称为递归体。
match=false;
return 0;
}
else{
char topSymbol;
topSymbol=openings.Pop();
match=(symbol=='}'&&topSymbol=='{') || //判断是否匹配
(symbol==')'&&topSymbol=='(') || (symbol==']'&&topSymbol=='[');
a1 a2 a3
top top top 进栈:top加1 出栈:top减1
栈空:top= -1 栈满:top= MAX_SIZE
顺序栈类的声明
const int maxSize=100; //表的最大尺寸 typedef int dataType; // 表元素为整型 class seqStack{
first
a1
a2
ai
an ∧
将哪一端作为栈顶? 将链头作为栈顶,方便操作。
链栈需要加头结点吗? 链栈不需要附设头结点。
栈的链接存储结构及实现
Байду номын сангаас
链栈:栈的链接存储结构
first
a1
a2
ai
top an
an-1
栈顶
a1 ∧
栈底
top an an-1
an ∧
栈顶
两种示意图在内存中 对应同一种状态
a1 ∧ 栈底
public: seqStack ( ) ; ~seqStack ( ); void Push (dataType x ); dataType Pop ( ); dataType GetTop ( ); bool Empty ( );
private: dataType data[maxSize]; int top;
private: node *top;
}
结点的定义如下: typedef int dataType; struct node {
dataType data; node *next; };
链栈的实现——插入
操作接口: void Push(dataType x);
top
xs
算法描述:
为 voidLinkStack::Push(dataType x)
队头
队尾
队列的逻辑结构
出队
a1 a2
}
顺序栈的实现——入栈
操作接口: void Push(dataType x ); void seqStack::Push (dataType x){ if (top==maxSize-1) throw “溢出”; top++; data[top]=x; }
时间复杂度?
顺序栈的实现——出栈
操作接口: dataType Pop( ); dataType seqStack:: Pop ( ){ if (top==-1) throw “溢出”; return data[top--]; }
问题2:考虑一下表达式的求值过程 1+2*3 → 123*+ → 7 1*2+3 → 12*3+ → 6
实际上,程序设计里面也有多处可见先进先出或后
进先出的现象。例如:函数调用
void a(); void b();
后进先出即为栈
main()
{ …. a( );
main
cout<< “return from a”;
int n,item; seqStack passengers; cout<<“输入乘客人数n”<<endl; cin>>n; cout<<“按上车顺序输入乘客编号”; cout<<endl; for (int i=0;i<n;i++){
cin>>item; passengers.push(item); } cout<<endl; cout<<“乘客的下车顺序是:”; while(!passengers.empty()) cout<<passengers.pop()<<“ ”; cout<<endl; }
}
顺序栈和链栈的比较
时间性能:相同,都是常数时间O(1)。 空间性能: 顺序栈:有元素个数的限制和空间浪费的问题。 链栈:没有栈满的问题,只有当内存没有可用空 间时才会出现栈满,但是每个元素都需要一个指针 域,从而产生了结构性开销。
总之,当栈的使用过程中元素个数变化较大时,用 链栈是适宜的,反之,应该采用顺序栈。
若相匹配,则“左括弧出栈” , 否则表明不匹配。 3)表达式检验结束时, 若栈空,则表明表达式中匹配正确, 否则表明“左括弧”有余。
算法:
bool matching(char exp[ ]) { int state=1;
ch=*exp++; while(ch!=‘#’&&state) {
switch of ch { case 左括号:{push(s,ch);break;} case ‘)’:{if(!Empty(s)&&GetTop(s)=‘(‘ ) pop(S,e); else state=0;break; }
top
an
an-1
什{
么 node *s=new node;
没 有
s->data=x;
判 s->next=top;
断 top=s;
a1 ∧
栈} 满 ?
链栈的实现——删除
操作接口: dataType Pop( );
top
an
p
top
an-1
a1 ∧
top++可以吗?
算法描述:
dataType LinkStack::Pop( ){ if (top==NULL) throw "下溢"; int x=top->data; node *p=top; top=top->next; delete p; return x;
链栈的类声明
typedef int dataType class LinkStack{
public: LinkStack( ); ~LinkStack( ); void Push(dataType x); dataType Pop( ); dataType GetTop( ); bool Empty( );
时间复杂度?
思考题:两栈共享空间问题
在一个程序中需要同时使用具有相同数据类型的 两个栈,如何顺序存储这两个栈? 解决方案1: 直接解决:为每个栈开辟一个数组空间。
会出现什么问题?如何解决? 解决方案2: 顺序栈单向延伸——使用一个数组来存储两个栈
栈的链接存储结构及实现
链栈:栈的链接存储结构
如何改造链表实现栈的链接存储?
}//matching
int main()
{
seqStack openings;
//存放尚未匹配的左括号
char symbol;
//用来记录当前符号的变量
bool match=true;
cout<<“请输入一个带括号的字符串"<<endl;