简介
三种实现方式,其实就是指,循环队列如何实现判空判满,区别就在这一块,原因是,如果不修改普通队列,会出现二义性,因为空满的状态其实是同一种状态。 下面介绍这三种方式。
方式一
通过空出一个位置,解决判空/满的冲突,这是第一次介绍循环队列,附上全部实现:
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