链式队列是基于单链表的一种存储表示
队列的对头指针指向单链表的第一个节点,队尾指针指向单链表的最后一个节点,
退出一个元素 则删除对头指针的节点,添加元素则在队尾增加一个节点
使用条件:数据元素变动比较大的情况。不存在溢出的情况
队列的抽象基类:
#ifndef QUEUE
#define QUEUE
//队列的抽象基类
template<class T>
class Queue
{
public:
Queue(){}
~Queue(){}
virtual bool EnQueue(const T& x)=0;
virtual bool DeQueue(T& x)=0;
virtual bool getFront(T& x)const=0;
virtual bool IsEmpty()const=0;
virtual bool IsFull()const=0;
virtual int getSize()const=0;
};
#endif
链式队列的具体实现:
/
#include"Stack.h"
#include <iostream>
//#include <cstdlib>
#include <cassert>
using namespace std;
template<class T>
struct LinkNode //链表节点类
{
T data;
LinkNode<T>* link;
LinkNode(LinkNode<T>* ptr=NULL):link(ptr){}
LinkNode(const T& item,LinkNode<T>* ptr=NULL):data(item),link(ptr){}
};
template<class T>
class LinkedQueue:public Queue<T>
{
public:
LinkedQueue():front(NULL),rear(NULL){}
~LinkedQueue(){makeEmpty();}
LinkedQueue(const LinkedQueue<T>& rhs);
LinkedQueue<T>& operator=(const LinkedQueue<T>& rhs);
bool EnQueue(const T& x);
bool DeQueue(T& x);
bool getFront(T& x)const;
bool IsEmpty()const{return (front==NULL)?true:false;}
bool IsFull()const{return false;}//无意义,永远不可能满
int getSize()const;
void makeEmpty();
friend ostream& operator<< <T>(ostream& os,const LinkedQueue<T>& rhs);
protected:
LinkNode<T> *front,*rear;
};
template<class T>
void LinkedQueue<T>::makeEmpty()
{
LinkNode<T>* p;
while(front!=NULL){
p=front;
front=front->link;
delete p;
}
rear=NULL;
}
template<class T>
bool LinkedQueue<T>::EnQueue(const T& x)
{
if(front==NULL){
front=rear=new LinkNode<T>(x);
if(front==NULL||rear==NULL)//对new返回值的一个检测,安全机制
return false;
}
else{
rear->link=new LinkNode<T>(x);
if(rear->link==NULL)
return false;
rear=rear->link;
}
return true;
}
template<class T>
bool LinkedQueue<T>::DeQueue(T& x)
{
if(IsEmpty())
return false;
LinkNode<T>* p=front;
if(front==rear){//只有一个节点的情况
front=front->link;
rear=NULL;
}else{
front=front->link;
}
x=p->data;
delete p;
return true;
}
template<class T>
bool LinkedQueue<T>::getFront(T& x)const
{
if(IsEmpty())
return false;
x=front->data;
return true;
}
template<class T>
int LinkedQueue<T>::getSize()const
{
int k=0;
LinkNode<T>* p=front;
while(p!=NULL){
++k;
p=p->link;
}
return k;
}
template<class T>
ostream& operator<<(ostream& os,const LinkedQueue<T>& rhs)
{
os<<"size: "<<rhs.getSize()<<endl;
LinkNode<T> *p=rhs.front;
os<<"elements:";
while(p!=NULL){
os<<p->data<<" ";
p=p->link;
}
os<<endl;
return os;
}
template<class T>
LinkedQueue<T>::LinkedQueue(const LinkedQueue<T>& rhs)
{
LinkNode<T> *src=rhs.front;
LinkNode<T> *dest=nullptr,*newNode=nullptr;
front=nullptr;
while(src!=NULL){
newNode=new LinkNode<T>(src->data);
if(front==nullptr){ //链表为无附加头结点的单链表,故比较特殊
front=newNode;
dest=newNode;
}else{
dest->link=newNode;
dest=newNode;
}
src=src->link;
}
rear=dest;
}
template<class T>
LinkedQueue<T>& LinkedQueue<T>::operator=(const LinkedQueue<T>& rhs)
{
makeEmpty();
LinkNode<T> *src=rhs.front;
LinkNode<T> *dest=nullptr,*newNode=nullptr;
front=nullptr;
while(src!=nullptr){
newNode=new LinkNode<T>(src->data);
if(front==NULL){
front=newNode;
dest=newNode;
}else{
dest->link=newNode;
dest=newNode;
}
src=src->link;
}
rear=dest;
return *this;
}
测试函数:
int main(int argc, char* argv[])
{
LinkedQueue<int> s;
int a=1,b=2,c=3,d=4,e=0;
s.EnQueue(a);
s.EnQueue(b);
s.EnQueue(c);
s.EnQueue(d);
cout<<s;
s.DeQueue(e);
s.DeQueue(e);
cout<<s;
cout<<"getSize(): "<<s.getSize()<<endl;
cout<<boolalpha;
cout<<"IsEmpty(): "<<s.IsEmpty()<<endl;
cout<<"IsFull(): "<<s.IsFull()<<endl;
cout<<noboolalpha;
s.getFront(e);
cout<<"getFront(): "<<e<<endl;
cout<<endl;
cout<<"copy and copy assignment"<<endl;
LinkedQueue<int> s1(s),s2;
cout<<s1;
s2=s;
cout<<s2;
system("pause");
return 0;
}
测试结果如下:
size: 4
elements:1 2 3 4
size: 2
elements:3 4
getSize(): 2
IsEmpty(): false
IsFull(): false
getFront(): 3
copy and copy assignment
size: 2
elements:3 4
size: 2
elements:3 4
请按任意键继续. . .
注意事项:
1.要对返回的指针值进行检测,比如用new时要对返回值进行检测,查看内存是否分配成功。这是随时随地的安全机制。
2.该实现所用的链表是没有附加头结点的单链表,所以拷贝构造函数和拷贝复制函数的编写要注意。
3.想清楚在写代码,否则漏洞很多。