如果队列的结构是单向的(如数组或单向链表),则经过若干队尾进、队头出之后,很可能会造成队列还没满却被认为已满或浪费空间的情况
。为了解决这一个问题,可以使用循环队列。使用循环队列的话,要解决判空和判满的条件的设定的问题,这里有几种解决方案:
1。rear指向队列的最后一个元素,front指向队列第一个元素的前一个位置,且这个位置保留不允许插入元素。在插入一个元素之前,如果
(rear + 1) % MAXSIZE == front的话,则不再插入且认为队列已满。而队空的条件是rear == front。 队列实际容纳的元素有MAXSIZE-1个。
2。设置一个标识变量,如果出队则设为0,如果入队则设为1,其它操作照常。队空的条件是flag == 0且rear == front,队满的条件是flag
== 1且rear == front。flag初始化为0。
这种方法可以变化一下,在队空时设rear为一个不可能的值(如-1、MAXSIZE等),而用front表示它实际的值(因为这时front == rear);在
队满时设front为一个不可能的值,而用rear表示它实际的值。这样可以省掉flag,但要考虑清楚一些细节。
3。设置一个size变量来表示队列实际元素的个数,则此时不必再作rear == front的判断了,rear和front的位置也不必再故意的设置了,只是
增加了存储空间即size的存储。
第1种方案的一个实现:
// 当然也可以让rear指向最后一个元素的后一个位置,front指向第一个元素,rear指向的位置保留(可移动)。
// 这里,front指向第一个元素的前一个位置(保留),rear指向最后一个元素。
//#include <cstdio> // for malloc/free
#include <iostream>
using namespace std;
#define ERROR -1
#define OK 0
#define OVERFLOW -2
#define EMPTY -3
#define MAXSIZE 10
typedef int STATUS;
typedef char ElementType;
typedef struct
{
int front;
int rear;
ElementType * pBase;
}Queue;
STATUS InitQueue(Queue * pQueue)
{
if (pQueue == NULL)
return ERROR;
pQueue->pBase = (ElementType*)malloc(sizeof(ElementType) * MAXSIZE);
if (pQueue->pBase == NULL)
return ERROR;
pQueue->front = pQueue->rear = 0;
return OK;
}
STATUS DestroyQueue(Queue * pQueue)
{
if (pQueue == NULL)
return ERROR;
if (pQueue->pBase)
{
free(pQueue->pBase);
}
return OK;
}
STATUS EnQueue(Queue * pQueue, ElementType & element)
{
if (pQueue == NULL || pQueue->pBase == NULL)
return ERROR;
if ((pQueue->rear + 1) % MAXSIZE == pQueue->front)
{
return OVERFLOW;
}
pQueue->rear = (pQueue->rear + 1) % MAXSIZE;
pQueue->pBase[pQueue->rear] = element;
return OK;
}
STATUS DeQueue(Queue * pQueue, ElementType & retElement)
{
if (pQueue == NULL || pQueue->pBase == NULL)
return ERROR;
if (pQueue->front == pQueue->rear)
return EMPTY;
pQueue->front = (pQueue->front + 1) % MAXSIZE;
retElement = pQueue->pBase[pQueue->front];
return OK;
}
STATUS Print(Queue * pQueue)
{
if (pQueue == NULL || pQueue->pBase == NULL)
return ERROR;
int nPos = pQueue->front + 1;
while (nPos != pQueue->rear)
{
cout << pQueue->pBase[nPos] << " ";
nPos = (nPos + 1) % MAXSIZE;
}
cout << pQueue->pBase[nPos] << " ";
return OK;
}
int main( )
{
Queue queue;
InitQueue(&queue);
cout << "Enter a string: ";
char c;
while ((c = getchar()) != '/n')
{
EnQueue(&queue, c);
}
cout << "this queue is: ";
Print(&queue);
cout << endl;
c = 0;
DeQueue(&queue, c);
cout << "dequeue one is : " << c << endl;
cout << "the queue is: ";
Print(&queue);
cout << endl;
DestroyQueue(&queue);
return 0;
}
第3种方案的一个实现:
// 加一个计数器
#include <iostream>
using namespace std;
#define ERROR -1
#define OK 0
#define OVERFLOW -2
#define EMPTY -3
#define MAXSIZE 10
typedef int STATUS;
typedef char ElementType;
typedef struct
{
int front;
int rear;
ElementType * pBase;
int cout;
}Queue;
STATUS InitQueue(Queue * pQueue)
{
if (pQueue == NULL)
return ERROR;
pQueue->pBase = (ElementType *)malloc(sizeof(ElementType) * MAXSIZE);
if (pQueue->pBase == NULL)
return ERROR;
pQueue->front = pQueue->rear = 0;
pQueue->cout = 0;
return OK;
}
STATUS DestroyQueue(Queue * pQueue)
{
if (pQueue == NULL)
return ERROR;
if (pQueue->pBase)
{
free(pQueue->pBase);
}
return OK;
}
STATUS EnQueue(Queue * pQueue, ElementType & e)
{
if (pQueue == NULL || pQueue->pBase == NULL)
return ERROR;
if (pQueue->cout >= MAXSIZE)
return OVERFLOW;
pQueue->rear = (pQueue->rear + 1) % MAXSIZE;
pQueue->pBase[pQueue->rear] = e;
pQueue->cout ++;
return OK;
}
STATUS DeQueue(Queue * pQueue, ElementType & retElement)
{
if (pQueue == NULL || pQueue->pBase == NULL)
return ERROR;
if (pQueue->cout == 0)
return EMPTY;
pQueue->front = (pQueue->front + 1) % MAXSIZE;
retElement = pQueue->pBase[pQueue->front];
pQueue->cout --;
return OK;
}
STATUS Print(Queue * pQueue)
{
if (pQueue == NULL || pQueue->pBase == NULL)
return ERROR;
int nPos = pQueue->front + 1;
while (nPos != pQueue->rear)
{
cout << pQueue->pBase[nPos] << " ";
nPos = (nPos + 1) % MAXSIZE;
}
cout << pQueue->pBase[nPos] << " ";
return OK;
}
int main( )
{
Queue queue;
InitQueue(&queue);
cout << "Enter a string: ";
char c;
while ((c = getchar()) != '/n')
{
EnQueue(&queue, c);
}
cout << "this queue is: ";
Print(&queue);
cout << endl;
c = 0;
DeQueue(&queue, c);
cout << "dequeue one is : " << c << endl;
cout << "the queue is: ";
Print(&queue);
cout << endl;
DestroyQueue(&queue);
return 0;
}