循環隊列
爲充分利用向量空間,克服”假溢出”現象的方法是:將向量空間想象爲一個首尾相接的圓環,並稱這種向量爲循環向量。存儲在其中的隊列稱爲循環隊列(Circular Queue)。這種循環隊列可以以單鏈表的方式來在實際編程應用中來實現。
循環隊列的問題
循環隊列中,由於入隊時尾指針向前追趕頭指針;出隊時頭指針向前追趕尾指針,造成隊空和隊滿時頭尾指針均相等。
因此,無法通過條件front==rear來判別隊列是”空”還是”滿”。
解決這個問題的方法至少有兩種:
1. 另設一布爾變量以區別隊列的空和滿;
2. 另一種方式就是數據結構常用的: 隊滿時:(rear+1)%n==front,n爲隊列長度(所用數組大小),由於rear,front均爲所用空間的指針,循環只是邏輯上的循環,所以需要求餘運算。
話不多說,先貼代碼再進行解釋
//來自於http://blog.csdn.net/nyhuachen/article/details/6422352
/************************************************************************/
/* author : thomas
E-mail: [email protected] */
/************************************************************************/
//循環隊列(數組實現)
#include <stdlib.h>
#include <stdio.h>
#define MAXSIZE 5
typedef int T;
typedef struct tag
{
int front, rear, MaxSize, count; //其實MaxSize變量完全可以不要
T elements[MAXSIZE];
} QUEUE;
定義了使用到的變量,包括front\rear\count等
front指定隊首位置,刪除一個元素就將front順時針移動一位;
rear指向元素要插入的位置,插入一個元素就將rear順時針移動一位;
count存放隊列中元素的個數,當count等於MaxSize時,不可再向隊列中插入元素。
void creat( QUEUE *queue )
{
queue -> front = 0;
queue -> rear = 0;
queue -> count = 0;
queue -> MaxSize = MAXSIZE - 1;
}
這個應該類似於java中的構造函數
int is_empty( QUEUE queue) //其實最好傳指針免得棧開銷太大
{
if ( queue.count == 0 )
{
return 1;
}
else
{
return 0;
}
}
int is_full( QUEUE queue )
{
if ( queue.count == MAXSIZE )
{
return 1;
}
else
{
return 0;
}
}
這是用了第一種判斷隊列滿的方式,只不過把bool型的變量轉換成了MAXSIZE以及count這兩個變量的求是否相等。
void readqueue( QUEUE queue ) //just read the value
{
if ( queue.count == 0 ) //可以用前面的is_empty函數進行判斷
{
printf("the queue is empty! no number is available! /n");
}
else
{
printf("the first number is %d /n", queue.elements[queue.front]);
}
}
void in_queue( QUEUE *queue, T value )
{
if ( queue -> count == MAXSIZE ) //可以利用前面的is_full函數進行判斷
{
printf("sorry! the queue is full! no space is available!/n");
}
else
{
if ( queue -> count == 0 )
{
//主要是處理隊列爲空時的入隊列
queue -> elements[queue -> rear] = value;
queue -> count += 1;
}
else
{
queue -> rear = (queue -> rear + 1) % MAXSIZE;
queue -> elements[queue ->rear] = value;
queue -> count += 1;
}
}
}
T out_queue( QUEUE *queue )
{
if ( queue -> count == 0 ) //可以利用前面的is_empty函數進行判斷
{
printf("sorry! the queue is empty! no number is available! /n");
exit(EXIT_FAILURE);
}
else
{
queue -> front = (queue -> front + 1) % MAXSIZE;
queue -> count -= 1;
return queue -> elements[queue -> front];
}
}
//print queue
void print( QUEUE queue )
{
int i = 1;/*count var*/
if ( queue.count == 0 )
{
printf("the queue is empty! no number can be printed! /n");
}
else
{
//count = queue.count;
printf("the number of queue is %d /n", queue.count);
for ( i; i <= queue.count; i++ )
{
printf("the %d number is %d /n", i, queue.elements[(queue.front + i - 1) % MAXSIZE]);
//printf("the %d number is %d /n", i, queue.elements[queue.front + i - 1]);
}
}
}
//test functions
void main(int argc, char *argv[])
{
QUEUE queue;
creat(&queue);
//out_queue(&queue);
in_queue(&queue, 2);
print(queue);
in_queue(&queue, 4);
print(queue);
in_queue(&queue, 5);
print(queue);
in_queue(&queue, 6);
print(queue);
in_queue(&queue, 1);
print(queue);
out_queue(&queue);
print(queue);
in_queue(&queue, 9);
print(queue);
//out_queue(&queue);
//print(queue);
in_queue(&queue, 7);
//print(queue);
}
其實這篇文章也想彙總下第二種方法對循環隊列判斷是否滿的解釋:
也即是
–>隊滿時: (rear+1)%maxsize=front
–>隊空時:rear=front
–>正常時:
這部分是http://blog.csdn.net/huangkq1989/article/details/5719529在其的文章處提到的
關鍵在於少用一個位置,用這個位置爲條件將循環隊列的邏輯循環(故之只能用%計算)顯式地表述出來。
有的時候退一步更能海闊天空=V=