常用數據結構之基於數組的循環隊列

         隊列是一種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;
}


          

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章