> For the complete documentation index, see [llms.txt](https://garychang.gitbook.io/data-structure/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://garychang.gitbook.io/data-structure/lecture1-stack-and-queue/lecture1.2-queue-lie.md).

# 1.2 - Queue

### 1. 介紹

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

![](/files/-LGjJ2PgttAq3IXc2VEF)

### 2. 基本操作

* Dequeue(): 從佇列的前端(Front)取出資料。
* Enqueue(): 將資料放到佇列的尾端(Rear)。
* IsEmpty(): 檢查是否佇列為空。
* IsFull(): 檢查佇列是否已滿。(當使用Array製作佇列時需注意是否已滿。)

#### 2.1 以Linear Link List來表示佇列的基本操作。

1. 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。

1. 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必須先宣告佇列的大小，所以佇列有可能會被填滿而無法再加入資料。

1. 設定佇列的大小

```
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來表示佇列的基本操作。

示意圖：

![](/files/-LGyB5UcFz4A66YZ50jQ)

特點：

* front和rear起始點在0
* front所指的位置之資料不使用(不算在佇列中)
* 最多使用n-1個位置

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來記錄佇列是空或是滿的狀態。

示意圖：

![](/files/-LGyGLjmo5odcg0cYbKf)

1. 宣告佇列參數

```
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>
