什麼是隊列?
隊列(Queue)也是一種運算受限的線性表。它只允許在表的一端進行插入,而在另一端進行刪除。允許刪除的一端稱爲隊頭(front),允許插入的一端稱爲隊尾(rear)。
FIFO原則
隊列具有先進先出原則,與棧的先進後出形成對比。
爲什麼設計循環隊列?
隊列的順序存儲結構稱爲順序隊列,順序隊列實際上是運算受限的順序表,和順序表一樣,順序隊列也是必須用一個向量空間來存放當前隊列中的元素。
入隊,出隊操作原理
由於隊列的隊頭和隊尾的位置是變化的,因而要設兩個指針和分別指示隊頭和隊尾元素在隊列中的位置,它們的初始值地隊列初始化時均應置爲0。入隊時將新元素插入所指的位置,然後將加1。出隊時,刪去所指的元素,然後將加1並返回被刪元素。
杜絕“假上溢”
和棧類似,隊列中亦有上溢和下溢現象。此外,順序隊列中還存在“假上溢”現象。因爲在入隊和出隊的操作中,頭尾指針只增加不減小,致使被刪除元素的 空間永遠無法重新利用。因此,儘管隊列中實際的元素個數遠遠小於向量空間的規模,但也可能由於尾指針巳超出向量空間的上界而不能做入隊操作。
爲充分利用向量空間。克服上述假上溢現象的方法是將向量空間想象爲一個首尾相接的圓環,並稱這種向量爲循環向量,存儲在其中的隊列稱爲循環隊列(Circular Queue)。在循環隊列中進行出隊、入隊操作時,頭尾指針仍要加1,朝前移動。只不過當頭尾指針指向向量上界(QueueSize-1)時,其加1操作的結果是指向向量的下界0。
實現代碼:
if(I+1 == QueueSize)
{
I = 0;
}
else
{
i++;
}
利用模運算可簡化爲:
何時隊列爲空?何時爲滿?
由於入隊時尾指針向前追趕頭指針,出隊時頭指針向前追趕尾指針,故隊空和隊滿時頭尾指針均相等。因此,我們無法通過front=rear來判斷隊列“空”還是“滿”。
注:先進入的爲‘頭’,後進入的爲‘尾’。
解決此問題的方法至少有三種:
其一是另設一個布爾變量以匹別隊列的空和滿;
其二是少用一個元素的空間,約定入隊前,測試尾指針在循環意義下加1後是否等於頭指針,若相等則認爲隊滿(注意:rear所指的單元始終爲空);
其三是使用一個計數器記錄隊列中元素的總數(實際上是隊列長度)。
隊列的基本操作:
數據元素定義
#include <stdio.h>
#include <assert.h>
#define QueueSize 100
typedef char datatype;
//隊列的數據元素
typedef struct
{
int front;
int rear;
int count; //計數器,用來記錄元素個數
datatype data[QueueSize]; //數據內容
}cirqueue;
隊列置空
//置空隊
void InitQueue(cirqueue *q)
{
q->front = q->rear = 0;
q->count = 0;
}
//判斷隊滿
int QueueFull(cirqueue *q)
{
return (q->count == QueueSize);
}
//判斷隊空
int QueueEmpty(cirqueue *q)
{
return (q->count == 0);
}
入隊
//入隊
void EnQueue(cirqueue *q, datatype x)
{
assert(QueueFull(q) == 0); //q滿,終止程序
q->count++;
q->data[q->rear] = x;
q->rear = (q->rear + 1)%QueueSize; //循環隊列設計,防止內存浪費
}
//出隊
datatype DeQueue(cirqueue *q)
{
datatype temp;
assert(QueueEmpty(q) == 0);//q空,則終止程序,打印錯誤信息
temp = q->data[q->front];
q->count--;
q->front = (q->front + 1)%QueueSize;
return temp;
}
- //取頭指針
- datatype QueueFront(cirqueue *q)
- {
- assert(QueueEmpty(q) == 0);
- return (q->data[q->front]);
- }
- //隊內有效長度
- (rear-front+N)%N
http://blog.csdn.net/to_dreams/article/details/7708051