队列是只允许在一端进行插入操作,在一端进行删除操作的线性表,允许插入的一端称为队尾,允许删除的一段称为队头.
队列具有先进先出的特性.现实世界有许多问题可以用队列描述,比如排队.而在程序设计中,也经常使用队列记录需要先进先出的方式处理的书,比如键盘缓冲区,操作系统中的作业调度等.
1)队列的顺序实现,循环队列.
由于单纯的设置头尾指针front,rear,随着头尾指针的移动,会出现假溢出的现象.所以可以把数组看成头尾相连的循环结构,即允许队列直接从数组中最大下标位置延续到最小下标位置,通过取模操作很容易实现.
队列空满的判断条件:
空:front = rear;
满:front = rear;
为了解决队满的判定条件,可以浪费一个数组元素空间,即(rear+1)%QueueSize = front;
实现:
#define QUEUE_SIZE 10
template <class T>
class CCirQueue
{
private:
T m_array[QUEUE_SIZE];
int front, rear; // 头尾指针
public:
CCirQueue();
~CCirQueue(){}
void EnQueue(T x); // 进队
T DeQueue(); // 出队
T GetQueue(); // 获取队头元素
bool Empty();
};
template <class T>
CCirQueue<T>::CCirQueue()
{
front = rear = 0;
}
template <class T>
void CCirQueue<T>::EnQueue(T x)
{
if ( (rear + 1) % QUEUE_SIZE == front)
{
throw "队列满";
}
rear = (rear + 1) % QUEUE_SIZE;
m_array[rear] = x;
}
template <class T>
T CCirQueue<T>::DeQueue()
{
if (front == rear)
{
throw "队列空";
}
front = (front + 1)%QUEUE_SIZE;
return m_array[front];
}
template <class T>
T CCirQueue<T>::GetQueue()
{
if (front == rear)
{
throw "队列空";
}
int n = (front + 1) % MAX_SIZE;
return m_array[n];
}
template <class T>
bool CCirQueue<T>::Empty()
{
return front == rear ? true : false;
}
2)队列的链接实现,链队列.
为了满足队列的操作特性,在单链表的基础上增加尾结点.
实现:
template <class T>
class CLinkQueue
{
private:
Node<T>* m_pFront;
Node<T>* m_pRear; // 队头,队尾指针
public:
CLinkQueue();
~CLinkQueue();
void EnQueue(T x);
T DeQueue();
T GetQueue();
bool Empty();
};
template <class T>
CLinkQueue<T>::CLinkQueue()
{
m_pFront = NULL;
m_pRear = NULL;
}
template <class T>
void CLinkQueue<T>::EnQueue(T x)
{
Node<T>* s = new Node<T>;
s->m_value = x;
s->pNextNode = NULL;
if (m_pFront == NULL)
{
m_pFront = s;
}
if (m_pRear == NULL)
{
m_pRear = s;
}else
{
m_pRear->pNextNode = s;
m_pRear = s;
}
}
template <class T>
T CLinkQueue<T>::DeQueue()
{
if (m_pFront == m_pRear && m_pFront == NULL && m_pRear == NULL)
{
throw "队列为空";
}
Node<T> * s = m_pFront;
int value = m_pFront->m_value;
if (m_pFront == m_pRear)
{
m_pFront = NULL;
m_pRear = NULL;
}else
{
m_pFront = m_pFront->pNextNode;
}
delete s;
return value;
}
template <class T>
T CLinkQueue<T>::GetQueue()
{
if (m_pFront == m_pRear && m_pFront == NULL && m_pRear == NULL)
{
throw "队列为空";
}
return m_pFront->m_value;
}
template <class T>
bool CLinkQueue<T>::Empty()
{
return ((m_pFront == m_pRear) && (m_pFront == NULL) && (m_pRear == NULL));
}
template <class T>
CLinkQueue<T>::~CLinkQueue()
{
while (m_pFront != NULL)
{
DeQueue();
}
}
3)循环队列和链队列的比较
与顺序栈和链栈的比较类似,只是循环队列不能像栈那样共享空间,通常不能在一个数组中存储两个循环队列.