采用链式存储结构实现的队列称为链队列(linked queue)。可以对单链表进行改造得到链队列,表头对应队头,表尾对应队尾。为了更方便操作,头指针为front,指向头结点。附设指向队尾结点的尾指针rear,空链队列和非空链队列如下图所示:
空链队列:
非空链队列:
结点结构可使用C++中的结构体定义,另外,由于链队列表中的元素类型并不确定,因此可以使用模板机制。
/*位于LinkStack.h文件中*/
/*用模板的方式定义数据结点*/
template <class ElemType>
struct Node
{
ElemType data;
Node<ElemType>* next;
};
可以使用C++语言的类模板LinkQueue描述链队列。由于队列是操作受限的线性表,因此链队列也可以看做是操作受限的单链表。
/*位于LinkQueue.h文件中*/
/*链队列的类定义及方法声明*/
template <class ElemType>
class LinkQueue{
public:
LinkQueue();/*构造函数,初始化空的链队列*/
~LinkQueue();/*析构函数,释放链队列中的所有结点*/
void EnQueue(ElemType x);//入队操作
ElemType DeQueue() ;//出队操作
ElemType GetQueue();//取队头
int Empty();//判断链队列是否为空
private:
Node<ElemType>* front ,*rear;//链队列的头指针和尾指针
};
构造函数初始化的链队列,只需要申请头结点,将front和rear赋初值。算法描述如下:
/*位于LinkQueue.cpp文件中*/
/*构造函数*/
template <class ElemType>
LinkQueue<ElemType>::LinkQueue()
{
front=new Node<ElemType>;
front->next=NULL;
rear=front;
}
析构函数将链队列中包括头结点在内的所有结点释放掉,执行完析构函数以后,front指针和rear指针都为NULL。算法描述如下:
/*位于LinkQueue.cpp文件中*/
/*析构函数*/
template <class ElemType>
LinkQueue<ElemType>::~LinkQueue()
{
while(front!=NULL)
{
Node<ElemType>* p=front;
front=front->next;
delete p;
}
rear = NULL;
}
/*位于LinkQueue.cpp文件中*/
/*入队操作*/
template <class ElemType>
void LinkQueue<ElemType>::EnQueue(ElemType x)
{
Node<ElemType>* s=new Node<ElemType>;
s->data=x;
s->next=NULL;
rear->next=s;
rear=s;
}
链队列的出队是在链表的表头删除一个结点。如果队列中包括的元素结点个数大于1,则不会影响到rear指针,因为队尾元素不变。但是如果队列中只包括一个元素结点,出队以后,链队列为空,此时需要将rear指针指向头结点,即rear=front。链队列出队操作如下图所示:
队列中只有一个元素结点:
队列中元素结点数大于1:
/*位于LinkQueue.cpp文件中*/
/*出队操作*/
template <class ElemType>
ElemType LinkQueue<ElemType>::DeQueue()
{
if(front==rear)
throw "链队列为空!";
/*p指向头指针*/
Node<ElemType>* p=front->next;
ElemType x=p->data;
front->next=p->next;
/*队列长度为1时,需要修改rear指针*/
if(p->next==NULL)
rear=front;
delete p;
return x;
}
/*位于LinkQueue.cpp文件中*/
/*取队头操作*/
template <class ElemType>
ElemType LinkQueue<ElemType>::GetQueue()
{
if(front==rear)
throw "链队列为空!";
else
return front->next->data;
}
/*位于LinkQueue.cpp文件中*/
/*判断空链队列操作*/
template <class ElemType>
int LinkQueue<ElemType>::Empty()
{
if(front==rear)
return 1;
else
return 0;
}
#include
#include "LinkQueue.h"
#include "LinkQueue.cpp"
using namespace std;
int main() {
LinkQueue<int> q;
if(q.Empty()==1)
cout<<"链队列为空"<<endl;
cout<<"元素2入队"<<endl;
q.EnQueue(2) ;
cout<<"元素4入队"<<endl;
q.EnQueue(4) ;
cout<<"元素6入队"<<endl;
q.EnQueue(6) ;
cout<<"队头元素为:" <<q.GetQueue()<<endl;
cout<<"队头出队"<<endl;
q.DeQueue();
cout<<"队头元素为:" <<q.GetQueue()<<endl;
if(q.Empty()==0)
cout<<"链队列不为空"<<endl;
return 1;
}
链队列为空
元素2入队
元素4入队
元素6入队
队头元素为:2
队头出队
队头元素为:4
链队列不为空
源代码地址