Transcript 第三章

第3章 栈和队列
3.1 栈
1、栈的基本概念
 栈:限定仅在表尾进行插入和删除操作的线性
表。
 空栈:不含任何数据元素的栈。
 允许插入和删除的一端称为栈顶,另一端称为
栈底。
1、栈的基本概念
入栈
栈顶
栈顶
栈顶
栈底
出栈
c
b
a
栈的示意图
插入:入栈、进栈、压栈
删除:出栈、弹栈
1、栈的基本概念
入栈
栈顶
栈顶
栈底
出栈
c
b
a
栈的示意图
插入:入栈、进栈、压栈
删除:出栈、弹栈
栈的操作特性:后进先出
2、栈的顺序存储结构及实现——顺序栈
如何改造数组实现栈的顺序存储?
1、确定用数组的哪一端表示栈底。
2、附设指针top指示栈顶元素在数组中的位置。
2、栈的顺序存储结构及实现——顺序栈
template <class T,int MaxSize >
class SeqStack
{
T data[MaxSize];
//存放栈元素的数组
int top; //栈顶指针,指示栈顶元素在数组中的下标
public:
SeqStack( ) ;
//构造函数
void Push(T x);
//入栈
T Pop( );
//出栈
T Top( );
//取栈顶元素(元素并不出栈)
bool Empty( );
//判断栈是否为空
};
2、栈的顺序存储结构及实现——顺序栈
顺序栈的操作算法:(P38-39)





初始化 SeqStack( )
入栈 Push(T x)
出栈 Pop( )
取栈顶元素 Top( )
判栈空 Empty( )
3、栈的链式存储结构及实现——链栈
如何改造链表实现栈的链接存储?
1、将哪一端作为栈顶?
2、链栈需要加头结点吗?
3、栈的链式存储结构及实现——链栈
链栈的类模板
template <class T>
class LinkStack
{
Node<T> *top;
//栈顶指针
public:
LinkStack( );
//构造函数
~LinkStack( );
//析构函数
void Push(T x);
//入栈
T Pop( );
//出栈
T Top( );
//取栈顶元素(元素不出栈)
bool Empty( );
//判断链栈是否为空栈
};
3、栈的链存储结构及实现——链栈
链栈的操作算法:(P39-40)





初始化 SeqStack( )
入栈 Push(T x)
出栈 Pop( )
取栈顶元素 Top( )
判栈空 Empty( )
4、栈的应用
 例1 把十进制整数转换为二至十六之间的
任一进制数输出。p52
 例2 括号匹配问题。试编写一个算法,用
来检查一个C++语言程序中的花括号、方
括号和圆括号是否配对,若能够全部配对则
返回1,否则返回0。p52
 例3 判回文
4、栈的应用
 中缀表达式求值是程序设计语言编译中的一个最基
本问题。它的实现需要借助栈来完成。这里介绍一
种简单直观,广为使用的算法,即“算符优先法”。
 为实现算符优先算法,可以使用两个工作栈。
 1.运算符OPTR栈, 用以寄存运算符;
 2.操作数OPND栈, 用以寄存操作数或运算结果。
算法思想:
 1)首先置操作数栈为空栈,表达式起始符
“@”为运算符的栈底元素;
 2)依次读入表达式中每个字符,若是操作
数则进OPND栈,若是运算符,则与
OPTR栈的栈顶运算符进行比较,作相应操
作,直至整个表达式求值完毕(即OPTR栈
的栈顶元素和当前读入的字符均为“@”)。
运算优先级
当前运算符
+
+
>
-
>
×
<
/
<
(
<
)
>
@
>
-
>
>
<
<
<
>
>
×
>
>
>
>
<
>
>
/
>
>
>
>
<
>
>
(
<
<
<
<
<
=
)
>
>
>
>
@
<
<
<
<
栈顶运算符
>
<
>
=
3.2队列
1、队列的逻辑结构
 队列:只允许在一端进行插入操作,而另一端
进行删除操作的线性表。
出队
a1
队头
a2
a3
入队
队尾
队列的操作特性: 先进先出
2、队列的顺序存储结构及实现(顺序队列)
如何改造数组实现队列的顺序存储?
1、仿照顺序表,将n个元素存放在前n个连续单元中。
入队操作时间性能为O(1),出队操作时间性能为O(n)
2、放宽队列的所有元素必须存储在数组的前n个连续单元这一条件 ,只要求
队列的元素存储在数组中连续的位置。——设置队头、队尾两个指示
入队操作时间性能为O(1),出队操作时间性能为O(1),但会出现假上溢
3、循环队列——将存储队列的数组头尾相接。
2、队列的顺序存储结构及实现(顺序队列)
如何实现循环队列?
1、不存在物理的循环结构,但可用软件方法实现
——求模
2、如何判断循环队列队空? front=rear
如何判断循环队列队满? front=rear
2、队列的顺序存储结构及实现(顺序队列)
队空、队满的判定条件出现二义性。
如何将队空和队满的判定条件分开?
方法一:浪费一个元素空间。将图3-8(c)所示的情况视为队满,此时的
状 态 是 , 队 尾 指 针 加 1就 会 从 后 面 赶 上 队 头 指 针 , 此 时 队 满 的 条 件 是
(rear+1) % MaxSize==front,这样就能与空队区别开。
方法二:设置一个布尔变量flag。当flag==flase时为空,当flag==true
时为满。
方法三:使用一个计数器记录队列中元素的个数。附设一个存储队列中元
素个数的变量如num,当num==0时队空,当num==MaxSize时队满
。
2、队列的顺序存储结构及实现(顺序队列)
template <class T, int MaxSize >
//定义类模板
SeqQueue
class SeqQueue
{
T data[MaxSize];
//存放队列元素的数组
int front, rear;
//队头和队尾指针
public:
SeqQueue( );
//构造函数,置空队
void EnQueue(T x);
//将元素x入队
T DeQueue( );
//将队头元素出队
T GetQueue( );
//取队头元素(并不删除)
bool Empty( );
//判断队列是否为空
};
2、队列的顺序存储结构及实现(顺序队列)
循环队列的操作:(P49-50)
(1)初始化
(2)入队
(3)出队
(4)判断队空
(5)判断队满
3、队列的链式存储结构及实现(链队列)
如何改造单链表实现队列的链接存储?
队头指针:指向链表的头结点
队尾指针:指向链表的尾结点
3、队列的链式存储结构及实现(链队列)
非空链队列
head
a1
a2
an ∧
rear
空链队列
front
∧
rear
3、队列的链式存储结构及实现(链队列)
template <class T>
class LinkQueue
{
public:
LinkQueue( );
//构造函数,初始化一个空的链队列
~LinkQueue( );
//析构函数,释放链队列中各结点的存储空间
void EnQueue(T x); //将元素x入队
T DeQueue( );
//将队头元素出队
T GetQueue( );
//取链队列的队头元素
bool Empty( );
//判断链队列是否为空
private:
Node<T> *front, *rear;
//队头和队尾指针,分别指向头结点和终端结点
};
3、队列的链式存储结构及实现(链队列)
链队列的操作:(P50-51)
(1)初始化
(2)入队
(3)出队