1.2 - Queue
Introduction of Queue(佇列的基本介紹及應用)
1. 介紹
佇列(Queue)是一種特殊的抽象資料結構,可以用鏈結串列(Link List)或陣列(Array)來表示,佇列的特點是資料的進出是同一方向的,在前端(Front)取出資料,在尾端(Rear)輸入資料,具有先進先出(FIFO, First-In-First-Out))的特性。

2. 基本操作
Dequeue(): 從佇列的前端(Front)取出資料。
Enqueue(): 將資料放到佇列的尾端(Rear)。
IsEmpty(): 檢查是否佇列為空。
IsFull(): 檢查佇列是否已滿。(當使用Array製作佇列時需注意是否已滿。)
2.1 以Linear Link List來表示佇列的基本操作。
Dequeue(): 回傳Front指標(指向佇列的前端)的資料。
int dequeue(){
if (isEmpty() == 1){
printf("The queue is empty.\n");
return 0;
}
else{
queue *output = front;
front = front->next; // the older data
free(output);
return output->Data; // return the top node
}
return -1;
}
2. Enqueue(): 將資料放入佇列的尾端。
void enqueue(int data){
// request space for new node
queue *new_node = (queue *)malloc(sizeof(queue));
// save the data to the new node
new_node->Data = data;
new_node->next = NULL;
// push to the back of the queue
if (isEmpty() == 1){
front = new_node;
rear = front;
}
else{
rear->next = new_node; // next of the rear node points to new node
rear = new_node;
}
}
3. 輸出結果範例:
Enqueue: 1, 2, 3
Queue: 1, 2, 3
Enqueue: 4, 5
Queue: 1, 2, 3, 4, 5
Dequeue, the front is: 1
Dequeue, the front is: 2
Queue: 3, 4, 5
完整程式碼: https://github.com/gary30404/Data-Structure/blob/master/1/1.2/queue_in_linklist.c
2.2 以Circular Link List來表示佇列的基本操作。
Circular Link List的特點是不需使用front指標,將rear指向front。
Dequeue(): 回傳Front指標(指向佇列的前端)的資料。
int dequeue(){
queue *t = (queue *)malloc(sizeof(queue)); //暫時的變數
if (rear == NULL){
printf("The queue is empty.\n");
return 0;
}
else{
if (rear->next == rear){ //代表佇列中只有一筆資料
t = rear;
rear = NULL;
return t->Data;
}
else{
t = rear->next; //t為front
rear->next = t->next; //目前的front會被輸出,rear指向當前的front的下一筆資料成為新的front
return t->Data;
}
}
return -1;
}
2. Enqueue(): 將資料放入佇列的尾端。
void enqueue(int data){
// request space for new node
queue *new_node = (queue *)malloc(sizeof(queue));
// save the data to the new node
new_node->Data = data;
if (rear == NULL){ //Queue原本為空
new_node->next = new_node;
}
else{
new_node->next = rear->next; //new_node為最後一筆資料,需指向front
rear->next = new_node; //將new_node加入linklist
}
rear = new_node; //新的rear
}
3. 輸出結果範例:
Enqueue: 1, 2, 3
Queue: 1, 2, 3
Enqueue: 4, 5
Queue: 1, 2, 3, 4, 5
Dequeue, the front is: 1
Dequeue, the front is: 2
Queue: 3, 4, 5
完整程式碼:https://github.com/gary30404/Data-Structure/blob/master/1/1.2/queue_in_circular_linklist.c
2.3 以Linear Array來表示佇列的基本操作。和Link List不同的是,使用Array必須先宣告佇列的大小,所以佇列有可能會被填滿而無法再加入資料。
設定佇列的大小
typedef struct queue{
int *Data;
int front;
int rear;
int MAX_SIZE;
}queue;
2. Dequeue(): 回傳佇列端的資料,並將每筆資料向前推移。所以在此演算法中,front永遠指向第一個元素。
int dequeue(queue *qu){
if (IsEmpty(qu) == 1){
printf("The queue is empty.\n");
return 0;
}
else{
int output = qu->Data[qu->front];
for (int i = 0;i < qu->rear; i++)
qu->Data[i] = qu->Data[i+1];
qu->Data[qu->rear] = 0;
qu->rear--;
return output;
}
return -1;
}
3. Enqueue(): 將資料放到佇列的後端。
void enqueue(queue *qu, int data){
if (IsFull(qu) == 1){
printf("The queue is full.\n");
}
else{
qu->Data[++qu->rear] = data;
}
}
4. 輸出結果範例:
Enqueue: 1, 2, 3
Queue: 1, 2, 3
Enqueue: 4, 5
Queue: 1, 2, 3, 4, 5
Dequeue, the front is: 1
Dequeue, the front is: 2
Queue: 3, 4, 5
完整程式碼:https://github.com/gary30404/Data-Structure/blob/master/1/1.2/queue_in_array.c
2.4 以Circular Array來表示佇列的基本操作。
示意圖:

特點:
front和rear起始點在0
front所指的位置之資料不使用(不算在佇列中)
最多使用n-1個位置
宣告佇列參數
void create_queue(queue *qu, int size){
qu->front = 0;
qu->rear = 0;
qu->MAX_SIZE = size;
qu->Data = (int *)malloc(sizeof(int) *size);
}
2. Dequeue(): 回傳佇列端的資料,並將front往下推移。
int dequeue(queue *qu){
if (qu->front == qu->rear){
printf("The queue is empty.\n");
return 0;
}
else{
qu->front = (qu->front + 1) % qu->MAX_SIZE;
return qu->Data[qu->front];
}
return -1;
}
3. Enqueue(): 將資料放到佇列的後端。
void enqueue(queue *qu, int data){
qu->rear = (qu->rear + 1) % qu->MAX_SIZE;
if (qu->front == qu->rear){
printf("The queue is full.\n");
qu->rear = (qu->rear + qu->MAX_SIZE - 1) % qu->MAX_SIZE;
}
else{
qu->Data[qu->rear] = data;
}
}
4. 輸出結果範例:
Create a queue which size is 5.
Enqueue: 1, 2, 3
Queue: 1 2 3
Enqueue: 4
Queue: 1 2 3 4
Enqueue: 5
The queue is full.
Dequeue, the front is: 1
Dequeue, the front is: 2
Queue: 3 4
完整程式碼:https://github.com/gary30404/Data-Structure/blob/master/1/1.2/queue_in_circular_array1.c
2.5 加上tag改善2.3的空間效率
在這裡使用變數tag來記錄佇列是空或是滿的狀態。
示意圖:

宣告佇列參數
void create_queue(queue *qu, int size){
qu->front = 0;
qu->rear = 0;
qu->tag = 0;
qu->MAX_SIZE = size;
qu->Data = (int *)malloc(sizeof(int) *size);
}
2. Dequeue(): 回傳佇列端的資料,並將front往下推移。
int dequeue(queue *qu){
if (qu->front == qu->rear && qu->tag == 0){
printf("The queue is empty.\n");
return 0;
}
else{
qu->front = (qu->front + 1) % qu->MAX_SIZE;
if (qu->front == qu->rear) qu->tag = 0; //檢查取出資料後佇列是否為空
return qu->Data[qu->front];
}
return -1;
}
3. Enqueue(): 將資料放到佇列的後端。
void enqueue(queue *qu, int data){
if (qu->front == qu->rear && qu->tag == 1){
printf("The queue is full.\n");
}
else{
qu->rear = (qu->rear + 1) % qu->MAX_SIZE;
qu->Data[qu->rear] = data;
if (qu->front == qu->rear) qu->tag = 1; //檢查輸入資料後佇列是否是滿的狀態
}
}
4. 輸出結果範例:
Create a queue which size is 5.
Enqueue: 1, 2, 3
Queue: 1 2 3
Enqueue: 4
Queue: 1 2 3 4
Enqueue: 5
The queue is full.
Dequeue, the front is: 1
Dequeue, the front is: 2
Queue: 3 4
完整程式碼:https://github.com/gary30404/Data-Structure/blob/master/1/1.2/queue_in_circular_array2.c
Last updated