队列是一种FIFO的存取方式,用数组来存储普通的队列时,一方面可能存储空间不够,另一方面容易出现“假溢出”。基于数组的循环队列避免不了第一个问题,但可以很好的解决第二个问题。下面是循环队列的结构图:
如图所示队空时rear=front,对满时rear在front的后面。顺序结构循环队列没有解决存储空间溢出的问题,在rear大于front时就会出现溢出而覆盖原有元素的现象。使得实际存储元素的个数有变化。通过用len =(rear - front + MAX_LEN)%MAX_LEN的方式来做到。
下面是其实现代码:
/*
* =====================================================================================
*
* Filename: 3queue.h
*
* Description: template of the queue
*
* Version: 1.0
* Created: 2012年03月13日 00时12分23秒
* Revision: none
* Compiler: gcc
*
* Author: Lavey Luo (lavey), luoyi.smt@gmail.com
* Organization:
*
* =====================================================================================
*/
#ifndef __QUEUE_H__
#define __QUEUE_H__
namespace st
{
#ifndef _STATUS_CONST_
#define _STATUS_CONST_
enum Status
{
OK = 0,
ERROR = -1
};
const int MAX_LEN = 20;
#endif
template<class T>
class queue
{
public:
explicit queue():rear(0), front(1){};
~queue(){};
public:
/* 初始化一个空队列Q */
Status Init();
/* 返回Q的元素个数,也就是队列的当前长度 */
int Length();
/* 若队列Q为空队列,则返回TRUE,否则返回FALSE */
Status Empty();
/* 将Q清为空队列 */
Status Clear();
/* 若队列不空,则用e返回队头元素,并返回OK,否则返回ERROR */
Status GetHead(T *e);
/* 若队列未满,则插入元素e为Q新的队尾元素 */
Status EnQueue(const T e);
/* 若队列不空,则删除Q中队头元素,用e返回其值 */
Status DeQueue(T *e);
private:
int rear;
int front;
T data[MAX_LEN];
};
template<class T>
Status queue<T>::Init()
{
rear = front = 0;
return OK;
}
template<class T>
Status queue<T>::Clear()
{
rear = front = 0;
return OK;
}
template<class T>
Status queue<T>::Empty()
{
if (rear == front)
return OK;
return ERROR;
}
template<class T>
int queue<T>::Length()
{
return (rear - front + MAX_LEN)%MAX_LEN;
}
template<class T>
Status queue<T>::GetHead(T *e)
{
if (rear == front) /* 队列空 */
return ERROR;
*e = data[front];
return OK;
}
template<class T>
Status queue<T>::EnQueue(const T e)
{
if ((rear+1)%MAX_LEN== front) /* 队列满的判断 */
return ERROR;
data[rear] = e; /* 将元素e赋值给队尾 */
rear = (rear+1)%MAX_LEN;/* rear指针向后移一位置, 若到最后则转到数组头部 */
return OK;
}
template<class T>
Status queue<T>::DeQueue(T* e)
{
if (front == rear) /* 队列空的判断 */
return ERROR;
*e = data[front]; /* 将队头元素赋值给e */
front = (front+1)%MAX_LEN; /* front指针向后移一位置, */
/* 若到最后则转到数组头部 */
return OK;
}
}
#endif
测试用例如下:
/*
* =====================================================================================
*
* Filename: test_queue.cpp
*
* Description: testcase of queue
*
* Version: 1.0
* Created: 2012年03月13日 10时18分30秒
* Revision: none
* Compiler: gcc
*
* Author: Lavey Luo (lavey), luoyi.smt@gmail.com
* Organization:
*
* =====================================================================================
*/
#include "3queue.h"
#include <stdio.h>
int test_queue(int argc, char** argv)
{
st::queue<int> q;
q.Init();
printf("初始化队列后,队列空否?%u(0:空 -1:否)\n",q.Empty());
printf("入队前,队列长度为: %d\n",q.Length());
for ( int i = 1; i < st::MAX_LEN ; i++)
q.EnQueue(i);
printf("入队后,队列长度为: %d\n",q.Length());
int d = 0;
q.GetHead(&d);
printf("现在队头元素为: %d\n",d);
printf("出队至只剩2个元素\n");
while (q.Length() > 2)
{
int e = 0;
q.DeQueue(&e);
printf(" %d", e);
}
puts("\n");
printf("出队后,队列长度为: %d\n",q.Length());
q.Clear();
printf("清空队列后, 队列空否?%u(0:空 -1:否)\n",q.Empty());
return 0;
}