下面从代码中理解分析队列的链式存储原理。
template<class T>
class Queue
{
public:
Queue();
~Queue();
bool isEmpty() const;
const T & getFront() const;
void enqueue (const T &x);
T dequeue();
void makeEmpty();
private:
///结点结构
struct Node
{
T element;
Node *next; //初始化为空
Node(const T& data,Node *n=0):element(data),next(n){}
};
Node *front; //队头
Node *rear; //队尾
};
/////////////////////////////////////////
template<class T>
Queue<T>::Queue()
{
front=rear=0; //类初始化,队头、队尾指针都为空
}
//////////////////////////////////////////
template<class T>
Queue<T>::~Queue() //析构函数
{
makeEmpty();
}
template<class T>
void Queueli<T>::makeEmpty()
{
front=rear=0;
}
////////////////////////////////////////////
template<class T>
bool Queue<T>::isEmpty() const //判断是队列是否为空
{
return front==0;
}
///////////////////////////////////////////
template<class T>
const T& Queue<T>::getFront() const
{
if(isEmpty()) throw "empty!";
return front->element;
}
/////////////////////////////////////////
template<class T>
void Queue<T>::enqueue(const T &x)
{
if(isEmpty())
rear=front=new Node(x);
else
rear=rear->next=new Node(x);
}
//////////////////////////////////////
template<class T>
T Queue<T>::dequeue()
{
T frontitem=getFront();
Node *old=front;
front=front->next;
delete old;//删除原front指向的对象,队头指向下一个对象
return frontitem;
}
重点理解一下队列元素的插入
template<class T>
void Queue<T>::enqueue(const T &x)
{
if(isEmpty())
rear=front=new Node(x); ..........................(1)
else
rear=rear->next=new Node(x); ..........................(2)
}
- 当队列为空,插入第一个结点时,队头队尾指针指向同一个结点,它们值相同,即上面所示的(1)式。
- 当插入第二个结点时,队尾指针指向的结点,也就是队头指针指向的结点(这点值得注意)的next指针由空被赋值为新元素的地址,即rear->next=new Node(x),此时等价于front->next=new Node(x),都是第一个结点的next指针被赋值;然后队尾指针rear赋值为新元素地址,队尾变更,即rear=new Node(x),此时rear指向的新结点中next指针为空。这两个过程合并起来就是上面所示的(2)式。
- 之后插入的结点的存储过程类似,先是rear指向的元素的空next指针被赋值为新元素的地址,然后新元素地址赋给队尾rear指针,产生新队尾。