簡介
三種實現方式,其實就是指,循環隊列如何實現判空判滿,區別就在這一塊,原因是,如果不修改普通隊列,會出現二義性,因為空滿的狀態其實是同一種狀態。 下面介紹這三種方式。
方式一
通過空出一個位置,解決判空/滿的沖突,這是第一次介紹循環隊列,附上全部實現:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
template <class ,int MAXSIZE > //定義類模板CirQueue class CirQueue { public : CirQueue(); ~CirQueue(); void EnQueue (T x) ; T DeQueue () ; T GetQueue () ; bool IsFull () ; bool Empty () ; private : T data[MAXSIZE]; int front,rear; };
隊列,其實很簡單,他是只允許在一端進行插入,而在另一端進行刪除的運算受限的線性表,所以比較容易掌握。
下面附上具體函數的實現:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
template <class ,int MAXSIZE >CirQueue <T,MAXSIZE>: :CirQueue(){ front=rear=0 ; } template <class ,int QueueSize >void CirQueue <T,QueueSize>: :EnQueue(T x){ if (IsFull()) { cout <<"上溢" <<endl ; return ; } rear = (rear+1 ) % QueueSize; data[rear] = x; } template <class ,int QueueSize > CirQueue <T,QueueSize>: :DeQueue(){ if (Empty()) { cerr <<"下溢" <<endl ; } front = (front+1 ) % QueueSize; return data[front]; } template <class T ,int QueueSize >T CirQueue <T,QueueSize>: :GetQueue(){ if (Empty()) { cerr <<"下溢" <<endl ; exit (0 ); } int i = (front+1 ) % QueueSize; return data[i]; } template <class T ,int QueueSize >bool CirQueue <T,QueueSize>: :Empty(){ return front == rear; } template <class T ,int QueueSize >bool CirQueue <T,QueueSize>: :IsFull(){ if ( (rear+1 ) % QueueSize == front) return true ; else return false ; }
下面對這個函數做個基本的測試。。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
int main () { CirQueue<int ,5 > Q; cout <<"塞滿隊列。。。" <<endl ; for (int i=0 ;;i++) { if (!Q.IsFull()) { Q.EnQueue(pow (2 ,i)); } else break ; } cout <<"取出頭元素:" ; cout <<Q.GetQueue()<<endl ; cout <<"依次出列:" ; while (!Q.Empty()) { cout <&l 大專欄 隊列的三種實現方式 t;Q.DeQueue()<<" " ; } return 0 ; }
測試結果如圖:
方式二
為了不浪費一個元素空間,加上一個布爾變量,在入隊操作時候把他變為true,如果flag為真,並且front==rear,那么表明隊伍滿了;在出隊的時候,把他設為false,如果最后一個操作為出隊,那么又遇到了front==rear,那么表明,這個時候隊伍是空的。代碼實現如下:
下面列出實現時候,與第一種的區別之處:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
template <class T ,int MAXSIZE >CirQueue <T,MAXSIZE>: :~CirQueue(){ } template <class T ,int MAXSIZE >CirQueue <T,MAXSIZE>: :CirQueue(){ front=rear=0 ; flag=false ; } template <class T ,int QueueSize >void CirQueue <T,QueueSize>: :EnQueue(T x){ if (IsFull()) { cout <<"上溢" <<endl ; return ; } rear = (rear+1 ) % QueueSize; data[rear] = x; flag=true ; } template <class T ,int QueueSize >T CirQueue <T,QueueSize>: :DeQueue(){ if (Empty()) { cerr <<"下溢" <<endl ; } front = (front+1 ) % QueueSize; flag=false ; return data[front]; } template <class T ,int QueueSize >T CirQueue <T,QueueSize>: :GetQueue(){ if (Empty()) { cerr <<"下溢" <<endl ; exit (0 ); } int i = (front+1 ) % QueueSize; return data[i]; } template <class T ,int QueueSize >bool CirQueue <T,QueueSize>: :Empty(){ if ( flag==false && front == rear ) return true ; else return false ; } template <class T ,int QueueSize >bool CirQueue <T,QueueSize>: :IsFull(){ if ( flag==true && front == rear ) return true ; else return false ; }
測試函數不做變動,測試結果如下:
方式三
用計數器來存儲個數,當計數器等於0的時候,空;當計數器等於MAXSIZE的時候,滿! 程序很簡單,不多說。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
template <class T ,int QueueSize >bool CirQueue <T,QueueSize>: :Empty(){ return count==0 ; } template <class T ,int QueueSize >bool CirQueue <T,QueueSize>: :IsFull(){ return count==QueueSize; }
測試結果和方法二同。
總結:
三種方法
還要注意一點:為了實現循環計數,要掌握下面的語句
raer=(rear+1)%MAXSIZE
front=(front+1)%MAXSIZE