隊列是一種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), [email protected]
* 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), [email protected]
* 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;
}