链式队列是基于单链表的一种存储表示
队列的对头指针指向单链表的第一个节点,队尾指针指向单链表的最后一个节点。
退出一个元素 则删除对头指针的节点。加入元素则在队尾添加一个节点
使用条件:数据元素变动比較大的情况。
不存在溢出的情况
队列的抽象基类:
#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.想清楚在写代码,否则漏洞非常多。