栈和队列
来源:互联网 发布:如何在excel筛选数据 编辑:程序博客网 时间:2024/05/22 13:48
【学习重点】
栈和队列的操作特性;
基于顺序栈和链栈的基本操作的实现;
基于循环队列和链栈的基本操作的实现;
一、栈
1. 栈的定义
栈是限定仅在表尾进行插入和删除操作的线性表,允许插入和删除的一端称为栈顶,另一端称为栈底,不含任何数据元素的栈称为空栈。栈中元素除了具有线性关系外还具有后进先出的特性。
2. 栈的抽象数据类型定义
ADT Stack
Data
栈中元素具有相同类型及后进先出的特点,相邻元素具有前驱和后继关系
Operation
InitStack
前置条件:栈不存在
输入:无
功能:栈的初始化
输出:无
后置条件:构造一个空栈
DestroyStack
前置条件:栈已存在
输入:无
功能:销毁栈
输出:无
后置条件:释放线性表栈所占用的存储空间
Push
前置条件:栈已存在
输入:元素值x
功能:入栈操作,在栈顶插入一个元素x
输出:如果插入不成功,则抛出异常
后置条件:如果插入成功,则栈顶增加了一个元素
Pop
前置条件:栈已存在
输入:无
功能:出栈操作,删除栈顶元素
输出:如果删除成功,返回被删除的元素值,否则抛出异常
后置条件:如果删除成功,则栈顶少了一个元素
GetTop
前置条件:栈已存在
输入:无
功能:取栈顶元素,读取当前的栈顶元素
输出:若栈不空,返回当前的栈顶元素
后置条件:栈不变
Empty
前置条件:栈已存在
输入:无
功能:判空操作,判断栈是否为空
输出:如果栈为空,返回1,否则返回0
后置条件:栈不变
endADT
2.栈的存储结构及实现
2.1栈的顺序存储结构——顺序栈
栈的顺序存储结构称为顺序栈
2.2顺序栈的实现
const intStackSize=10;
template<classDataType>
class SeqStack
{public:
SeqStack(){top=-1;}
~SeqStack(){}
void Push(DataTypex);
DataType Pop();
DataTypeGetTop(){if(top!=-1)return data[top];
intEmpty(){top==-1?return 1:return 0;}
private:
DataTypedata[StackSize];
int top;};
(1)栈的初始化
初始化栈只需将栈顶元素指针top置为-1.
(2)顺序栈入栈操作
在栈中插入一个元素x只需将栈顶指针top加1,然后在top指向的位置填入元素x,算法如下:
template<classDataType>
voidSeqStack<DataType>::Push(DataType x)
{
if(top==StackSize-1)throw"上溢"
data[++top]=x;}
(3)顺序栈出栈操作
删除栈顶元素只需取出栈顶元素,然后将栈顶指针top-1,算法如下:
template<classDataType>
voidSeqStack<DataType>::pop()
{
if(top==-1)throw"下溢"
x=data[top--];
return x;}
(4)取栈顶元素
取栈顶元素只是将top指向的栈顶元素取出,并不修改栈顶指针。
(5)判空操作
判空操作只需判断top==1是否成立,如果成立,则栈为空,返回1;如果不成立,则栈非空,返回0.
3. 两栈共享空间
抽象数据类型定义如下:
ADT BothStack
Data
共享的数组空间长度StackSize
存放栈元素的数组data[StackSize]
栈1的栈顶指针top1
栈2的栈顶指针top2
Operation
BothStack
前置条件:共享数组空间不存在
输入:无
功能:创建两栈共享的数组空间
输出:无
后置条件:两栈均为空,top1=-1,top2=StackSize
~BothStack
前置条件:共享空间已存在
输入:无
功能:销毁两栈共享的数组空间
输出:无
后置条件:将两栈共享的数组空间释放
GetTop
前置条件:共享空间已存在
输入:栈号i
功能:读取栈i当前的栈顶元素
输出:若栈i不为空,返回栈i当前的栈顶元素
后置条件:两栈均不变
Push
前置条件:共享空间已存在
输入:栈号i,元素值x
功能:入栈操作,在栈i中插入元素x
输出:若插入不成功,则抛出异常
后置条件:若插入成功,则栈i插入了一个栈顶元素
Pop
前置条件:共享空间已存在
输入:栈号i
功能:出栈操作,在栈i中删除栈顶元素
输出:若删除不成功,则抛出异常
后置条件:删除成功,则栈中删除了栈顶元素
Empty
前置条件:共享空间已存在
输入:栈号i
功能:判空操作,判断栈i是否为空栈
输出:若栈i是空栈,则返回1,否则返回0
后置条件:两栈均不变
endADT
对应的c++类声明如下:
const intStackSize=100;
template <classDataType>
class BothStack
{
public:
BothStack(){top1=-1;top2=StackSize;}
~BothStack(){}
void Push(inti,DataType X);
DataType Pop(inti);
DataTypeGetTop(int i);
int Empty(int i);
private:
DataTypedata[StackSize];
int top1,top2;};
(1)入栈操作
当存储栈的数组中没有空闲单元时为栈满,此时栈1的栈顶元素和栈2的栈顶元素位于数组中的相邻位置,即top1=top2-1,另外,当新元素插入栈2时,栈顶指针top2不是加1而是减1,算法如下:
两栈共享空间入栈算法Push
template <classDataType>
voidBothStack<DataType>::Push(int i,DataType x)
{
if(top1==top2-1)throw"上溢";
if(i==1)data[++top1]=x;
if(i==2)data[--top2]=x;}
(2)出栈操作
当top1=-1时栈1为空;当top2=StackSize时栈2为空。另外,当栈2删除元素时,栈顶指针top2不是减一而是加一,算法如下:
template <classDataType>
DataTypeBothStack<DataType>::Pop(int i)
{
if(i==1){if(top1==-1)throw"下溢";
returndata[top1--];
}
if(i==2){if(top2==StackSize)throw"下溢";
returndata[top2++];}}
4.栈的链接存储结构及实现
4.1栈的链接存储结构---链栈
栈的链接存储结构称为链栈
4.2链栈的实现
template <classDataType>
class LinkStack
{
public:
LinkStack(){top=NULL;}
~LinkStack();
void Push(DataTypex);
DataType Pop();
DataTypeGetTop(){if(top!=NULL)return top->data;}
intEmpty(){top==NULL?return 1:return 0;}
private:
Node<DataType>*top;};
(1)构造函数
构造函数的作用是初始化一个空的链栈,由于链栈不带头结点,因此只需将栈顶指针top置为空。
(2)入栈操作
链栈的插入操作只需处理栈顶即第一个位置的情况,而无需考虑其他位置的情况,其算法如下:
template <classDataType>
voidLinkStack<DataType>::Push(DataType x)
{
s=new Node;s->data=x;
s->next=top;top=s;}
(3)出栈操作
链栈的出栈操作只需处理栈顶即第一个位置的情况,而无需考虑其他位置的情况。算法如下:
template <classDataType>
DataTypeLinkStack<DataType>::Pop()
{
if(top==NULL)throw"下溢";
x=top->data;p=top;
top=top->next;
delete p;
return x;}
(4)取栈顶元素
取栈顶元素只需返回栈顶指针top所在的结点的数据域。
(5)判空操作
栈链的判空操作只需判断top==NULL是否成立。如果成立,则栈为空,返回1;如果不成立,则栈非空,返回0.
(6)析构函数
链栈的析构函数需要将链栈中所有结点的存储空间释放,算法与单链表类的析构函数类似。
5.顺序栈和链栈的比较
链栈没有栈满问题,只有当内存没有可用空间时才会出现栈满情况,但是每一个元素都需要一个指针域,从而产生了结构性开销。所以当栈的使用过程中元素个数变化较大时,用链栈是适宜的;反之,应采用顺序栈。
二、队列
1.队列的逻辑结构
1.1队列的定义
队列时只允许在一端进行插入操作,在另一端进行删除操作的线性表。允许插入的一端称为队尾,允许删除的一端称为队头。其具有先进先出的特性。
1.2队列的抽象数据类型定义
ADT Queue
Data
队列中元素具有相同类型及先进先出的特点,相邻元素具有前驱和后继关系
Operation
InitQueue
前置条件:队列不存在
输入:无
功能:队列的初始化
输出:无
后置条件:创建一个空队列
DestroyQueue
前置条件:队列已存在
输入:无
功能:销毁队列
输出:无
后置条件:释放队列所占用的存储空间
EnQueue
前置条件:队列已存在
输入:元素值x
功能:入队操作,在队尾插入一个元素x
输出:如果插入不成功,则抛出异常
后置条件:如果插入成功,则队尾增加了一个元素
DeQueue
前置条件:队列已存在
输入:无
功能:出队操作,删除队头元素
输出:如果删除成功,返回被删除的元素值,否则抛出异常
后置条件:如果删除成功,则队头少了一个元素
GetQueue
前置条件:队列已存在
输入:无
功能:读取当前的队头元素
输出:若队列不空,返回当前的队头元素
后置条件:队列不变
Empty
前置条件:队列已存在
输入:无
功能:判空操作,判断队列是否为空
输出:如果队列为空,返回1,否则返回0
后置条件:队列不变
endADT
2.队列的顺序存储结构及实现
2.1队列的顺序存储结构——循环队列
队列的这种头尾相接的顺序存储结构成为循环队列。
2.2循环队列的实现
const intQueueSize=100;
template<classDataType>
class CirQueue
{
public:
CirQueue(){front=rear=QueueSize-1;}
~CriQueue(){}
void EnQueue(DataTypex);
DataTypeDeQueue();
DataTypeGeQueue();
intEmpty(){front==rear?return1:return 0;}
private :
DataTypedata[QueueSize];
int front,rear;};
(1)构造函数
其作用是初始化一个空的循环队列,只需将队头指针和队尾指针同时指向数组中的某一个位置,一般是数组的高端,即rear=front=QueueSize-1.
(2)入队操作
循环队列的入队操作只需将队尾的指针rear在循环意义下加1,然后将带插入元素x 插入队尾位置。算法如下:
template<classDataType>
voidCirQueue<DataType>::EnQueue(DataType x)
{
if((rear+1)%QueueSize==front)throw"上溢";
rear=(rear+1)%QueueSize;
data[rear]=x;}
(3)出队操作
循环队列的出队操作只需将队头的指针front在循环意义下加1,然后读取并返回队头元素。算法如下:
循环队列的出队算法DeQueue
template<classDataType>
voidCirQueue<DataType>::DeQueue()
{
if(rear==front)throw"下溢";
i=(front+1)%QueueSize;
return data[i];}
(4)读取队头元素
template<classDataType>
DataTypeCirQueue<DataType>::GetQueue()
{
if(rear==front)throw"下溢";
i=(front+1)%QueueSize;
return data[i];}
(5)判空操作
循环队列的判空操作只需判断front==rear是否成立。如果成功,则队列为空,返回1;如果不成立,则队列非空,返回0。
3.队列的链接存储结构及实现
3.1队列的链接存储结构—链队列
队列的链接存储结构称为链队列。
3.2链队列的实现
template<classDataType>
class LinkQueue
{
public:
LinkQueue();
~LinkQueu();
voidEnQueue(DataType x);
DataTypeDeQueue();
DataTypeGetQueue();
intEmpty(){front==rear?return1:return0;}
Private:
Node<DataType>*front,*rear;};
(1)构造函数
构造函数的作用是初始化一个空的链队列,只需申请一个头结点,然后让队头指针和队尾均指向头结点,算法如下:
链队列构造函数算法LinkQueue
template<classDataType>
LinkQueue<DataType>::LinkQueue()
{
s=newNode;s->next=NULL;
front=rear=s;}
(2)入队操作
链队列的插入操作只考虑在链表的尾部进行,由于链队带头结点,空链队列和非空链队列的入队操作语句一致。算法如下:
链队列入队算法EnQueue
template<classDataType>
voidLinkQueue<DataType>::EnQueue(DataType x)
{
s=newNode;s->data=x;
s->next=NULL;
rear->next=s;
rear=s;}
(3)出队操作
链队列出队操作DeQueue
template<classDataType>
DataTypeLinkQueue<DataType>::EnQueue()
{
if(rear==front)throw"下溢";
p=front->next;x=p->data;
front->next=p->next;
if(p->next==NULL)rear=front;
delete p;
return x;}
(4)取队头操作
取链队列的队头元素只需返回第一个元素结点的数据域,即返回first->next->data
(5)判空操作
判断front==rear是否成立。如果成立,则队列为空,返回1,如果不成立,则队列非空,返回0.
- 栈和队列--队列
- 【栈和队列】队列
- 栈、队列和优先队列
- 栈和队列(队列)
- 栈和队列--栈
- 【栈和队列】栈
- 栈和队列
- 栈和队列
- 表、栈和队列
- 栈和队列
- 栈和队列应用
- 栈和队列
- 栈和队列
- 栈和队列
- 栈和队列
- 栈和队列
- 队列和栈
- 栈和队列 小结
- poj 1204 Word Puzzles(字典树)
- 用户定位(gps,network)
- C++:sprintf()的用法
- C++中引用(&)的用法和应用实例(转自博客园文章)
- C#写水仙花数--用到递归
- 栈和队列
- 科技人才应具备的8个“杀手锏”级软技能
- 2014 Asia AnShan Regional Contest 题解
- IOS下点击按钮后退到上一个界面
- 【掌沃WiFi商盟】如何创建砸金蛋活动
- Java程序如何生成Jar、exe及安装文件
- POJ 3692 Kindergarten(最大独立集)
- 绘制球赛贝尔图
- 【原创】《Linux高级程序设计》杨宗德著 - 进程管理与程序开发 - 进程资源及属性