队列简介
队列分析
代码演示
队列简介
定义
队列到底是什么?百度上是这么说的:
队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。队列中没有元素时,称为空队列。
而在我的理解看来,数据结构当中的队列其实和我们生活当中的排队差不多,我们去排队买茶颜的时候,就是先到的的人排队在前面,后到的就排在后面,最前面的就是队头,最后面的就是队尾。队伍的增加也是后面的人从后面排入,买完茶颜离开的时候就是从队头离开的。我们数据结构当中的队列也是如此,从后面插入元素,从前面删除元素。
分类
1.顺序队列:
建立顺序队列结构必须为其静态分配或动态申请一片连续的存储空间,并设置两个指针进行管理。一个是队头指针front,它指向队头元素;另一个是队尾指针rear,它指向下一个入队元素的存储位置
顾名思义,顺序队列就是像我们平时排队一样,一条线,大长队。但是顺序队列有一个缺点,前面的人走了以后,空间是空下来的,会导致浪费空间,因此,为了能够使空间重复利用,我们就会使用下面的环形队列。
2.环形队列:
在实际使用队列时,为了使队列空间能重复使用,往往对队列的使用方法稍加改进:无论插入或删除,一旦rear指针增1或front指针增1 时超出了所分配的队列空间,就让它指向这片连续空间的起始位置。自己真从MaxSize-1增1变到0,可用取余运算rear%MaxSize和front%MaxSize来实现。这实际上是把队列空间想象成一个环形空间,环形空间中的存储单元循环使用,用这种方法管理的队列也就称为循环队列。除了一些简单应用之外,真正实用的队列是循环队列。
环形队列就是头和尾连在了一起,实际上我们一般都是使用环形队列,这个更加靠谱一些。
队列分析
1.简单分析:队列是一个类,既然是一个类,那么必然会有属性和方法。对于属性,我们可以简单的思考一下,我们平时排队都会有队头和队尾,因此,队列也是有队头和队尾的,我们需要进行在属性当中标记。而队伍肯定是有长度的,我们进行遍历的时候就必须知道,队伍长度的大小,才能有循环。我们也可以把队列的最大长度限定一下,因此可以有一个容量。既然队列是一个个元素排成一条队,我们就可以定义一个指针数组。
因此,属性有:
private:
int *m_queue; //队列数组指针
int length; //队列元素个数
int capacity; //队列容量
int head; //队头标记
int tail; //队尾标记,都用数组下标表示
而对于一个这样的队列,我们肯定会要有构造函数进行初始化,分配空间,析构函数去回收空间,清空队列的函数,判断队列是否为空,入队函数(添加元素),出队函数(删除元素),遍历函数等等:
方法:
Queue(int pcapacity) //构造函数
virtual ~Queue() //析构函数
void clear() //清空队列
bool Empty() //判断队列是否为空
bool queueFull()
int Queuealength() //返回队列长度
bool push(int element) //入队
bool pop(int &element) //队头出队
void queueTraverse() //遍历队列
代码演示
构造函数:我们可以给队列限制一个初始容量,然后把属性初始化,定义数组。
Queue(int pcapacity) //构造函数
{
capacity=pcapacity;
head=0;
tail=0;
length=0;
m_queue=new int[capacity];
}
析构函数与清空队列函数:
virtual ~Queue() //析构函数
{
delete []m_queue;
m_queue=NULL;
}
void clear() //清空队列
{
head=0;
tail=0;
length=0;
}
判断是否为空:只需要判断队列长度大小就可以了,长度为0,自然就是空了。
bool Empty() //判断队列是否为空
{
if(length==0)
{
return true;
}
else
{
return false;
}
}
入队:每入一次队,我们都要改变队尾的位置,把下标加一,但是我们不能越界,容量只有那么多,那么我们就需要进行特殊的处理,入一次队,队伍长度加一。
bool push(int element) //入队
{
if(queueFull())
{
return false;
}
else
{
m_queue[tail]=element;
tail++;
tail=tail%capacity; //防止tail越界,若超过。则超过部分继续从零开始。
length++;
return true;
}
}
出队:每出队一次,队头的位置就会改变,我们就需要加一,长度减一,但是队头也不能溢出,以此也要像队尾下标一样处理:
bool pop(int &element) //队头出队
{
if(Empty())
{
return false;
}
else
{
element=m_queue[head];
head++;
head=head%capacity;
length--;
return true;
}
}
遍历:
void queueTraverse() //遍历队列
{
for(int i=head;i<length+head;i++)
{
cout<<m_queue[i%capacity]<<endl;
}
cout<<endl;
}
队列还是挺接近我们的现实生活的,可以相互联系一下,它和栈有那么些许类似。