队列是一种特殊的线性表。
队列仅能在线性表的两端进行操作
队头(Front):取出数据元素的一端。
队尾(Rear):插入数据元素的一端。
队列的特性:先进先出(First in first out)
操作:创建队列(queue()),销毁,清空,进,出,获取队头,长度
StaticQueue设计要点:类模板,使用原生数组作为队列的存储空间,使用模板参数决定队列的最大容量。
StaticQueue实现要点(循环计数法(高效))
关键操作:
进队列:m_space[m_rear]=e;m_rear=(m_rear+1)%N //取余
出队列:m_front=(m_front+1)%N;
队列的状态:
队空:(m_length==0)&&(m_front==m_rear)
队满:(m_length==N)&&(m_front==m_rear)
#ifndef STATICQUEUE_H_
#define STATICQUEUE_H_
#include "Queue.h"
#include "Exception.h"
namespace WSlib
{
template<typename T,int N>
class StaticQueue:public Queue<T>
{
protected:
T m_space[N];
int m_front;
int m_rear;
int m_length;
public:
StaticQueue()
{
m_front=0;
m_rear=0;
m_length=0;
}
int capacity()const
{
return N;
}
void add(const T& e)
{
if(m_length<N)
{
m_space[m_rear]=e;
m_rear=(m_rear+1)%N;
m_length++;
}
else
{
THROW_EXCEPTION(InvalidOperationException,"No space in current queue");
}
}
void remove()
{
if(m_length>0)
{
m_front=(m_front+1)%N;
m_length--;
}
else
{
THROW_EXCEPTION(InvalidOperationException,"No element in current queue");
}
}
T front() const
{
if(m_length>0)
{
return m_space[m_front];
}
else
{
THROW_EXCEPTION(InvalidOperationException,"No element in current queue");
}
}
void clear()
{
m_front=0;
m_rear=0;
m_length=0;
}
int length()const
{
return m_length;
}
};
}
#endif
/**************************************************8
#include <iostream>
#include "StaticQueue.h"
using namespace std;
using namespace WSlib;
int main()
{
StaticQueue<int,5> q ;
for(int i=0;i<5;i++)
{
q.add(i);
}
while(q.length()>0)
{
cout<<q.front()<<endl;
q.remove();
}
return 0;
}
******************************************************/
小结:队列是一种特殊的线性表,具有先进先出的特性。队列只允许在线性表的两端进行操作,一端进,一端出。StaticQueue使用原生数组作为内部存储空间。StaticQueue的最大容量由模板参数决定。StaticQueue采用循环计数法提高队列操作的效率。
37、链式队列的设计要点
类模板,抽象父类Queue的直接子类,在内部使用链式结构实现元素的存储,只在链表的头部和尾部进行操作。
使用LinkList类实现链式队列是否合适,是否有更好的方案?
#ifndef LINKQUEUE_H_
#define LINKQUEUE_H_
#include "Queue.h"
#include "LinkList.h"
namespace WSlib
{
template <typename T>
class LinkQueue:public Queue<T>
{
protected:
LinkList<T> m_list;
public:
LinkQueue()
{
}
void add(const T& e) //o(n)
{
m_list.insert(e); //尾部
}
void remove() //o(1)
{
if(m_list.length()>0)
{
m_list.remove(0); //头部
}
else
{
THROW_EXCEPTION(InvalidOperationException,"No element in current queue");
}
}
T front() const //o(1)
{
if(m_list.length()>0)
{
return m_list.get(0);
}
else
{
THROW_EXCEPTION(InvalidOperationException,"No element in current queue");
}
}
void clear() //o(n)
{
m_list.clear();
}
int length()const //o(1)
{
return m_list.length();
}
};
}
#endif
/**************************
#include <iostream>
#include "LinkQueue.h"
using namespace std;
using namespace WSlib;
int main()
{
LinkQueue<int>lq;
for(int i=0;i<10;i++)
{
lq.add(i);
}
while(lq.length()>0)
{
cout<<lq.front()<<endl;
lq.remove();
}
return 0;
}
*************************/
基于linux:
#ifndef LINKQUEUE_LINUX_H_
#define LINKQUEUE_LINUX_H_
#include "Queue.h"
#include "LinuxList.h"
#include "Exception.h"
namespace WSlib
{
template <typename T>
class LinkQueue_linux:public Queue<T>
{
protected:
struct Node:public Wobject
{
list_head head;//链表头成员
T value;
};
list_head m_header;
int m_length;
public:
LinkQueue_linux() //o(1)
{
m_length=0;
INIT_LIST_HEAD(&m_header);
}
void add(const T& e) //o(1)
{
Node* node=new Node();
if(node != NULL)
{
node->value=e;
list_add_tail(&node->head,&m_header);
m_length++;
}
else
{
THROW_EXCEPTION(InvalidOperationException,"No element in current queue");
}
}
void remove() //o(1)
{
if(m_length>0)
{
list_head* toDel=m_header.next;
list_del(toDel);
m_length--;
delete list_entry(toDel,Node,head);
}
else
{
THROW_EXCEPTION(InvalidOperationException,"No element in current queue");
}
}
T front() const //o(1)
{
if(m_length>0)
{
return list_entry(m_header.next,Node,head)->value;
}
else
{
THROW_EXCEPTION(InvalidOperationException,"No element in current queue");
}
}
void clear() //o(n)
{
while(m_length>0)
{
remove();
}
}
int length()const //o(1)
{
return m_length;
}
~LinkQueue_linux() //o(n)
{
clear();
}
};
}
#endif
/******************************************************
#include <iostream>
#include "LinkQueue_linux.h"
#include "StaticQueue.h"
using namespace std;
using namespace WSlib;
class Test:public Wobject
{
public:
Test()
{
cout<<"Test()"<<endl;
}
~Test()
{
cout<<"~Test()"<<endl;
}
};
int main()
{
LinkQueue_linux <Test> lq;
StaticQueue<Test,5> l;
for(int i=0;i<10;i++)
{
//lq.add(i);
}
while(lq.length()>0)
{
//cout<<lq.front()<<endl;
lq.remove();
}
return 0;
}
********************************************************/
StaticQueue在初始化时可能多次调用元素类型的构造函数,LinkList的组合使用能够实现队列的功能(插入尾部效率低),但是不够高效,LinkQueue的最终实现组合使用了Linux内核链表,LinkQueue_linux中入队和出队操作可以在常量时间内完成。