Data Structure
  • 資料結構自學筆記
  • 1 - Stack & Queue
    • 1.1 - Stack
    • 1.2 - Queue
    • 1.3 - Stack and Queue
  • 2 - Tree & Binary Tree
    • 2.1 - Tree
    • 2.2 - Binary Tree
    • 2.3 - Binary Tree Traversal
    • 2.4 - Binary Search Tree
    • 2.5 - Heap
    • 2.6 - Thread Binary Tree
    • 2.7 - Tree and Binary Tree Conversion
    • 2.8 Advanced Trees
      • 2.8.1 - Min-Max Heap
      • 2.8.2 - Deap
      • 2.8.3 - Symmetric Min-Max Heap
      • 2.8.4 - Extended Binary Tree
      • 2.8.5 - AVL Tree
      • 2.8.6 - M-Way Search Tree
      • 2.8.7 - B Tree
      • 2.8.8 - Red-Black Tree
      • 2.8.9 - Optimal Binary Search Tree
      • 2.8.10 - Splay Tree
      • 2.8.11 - Leftest Heap
      • 2.8.12 - Binomial Heap
  • 3 - Search & Sort
    • 3.1 - Searching
    • 3.2 - Elementary Sorting
      • 3.2.1 - Insertion Sort
      • 3.2.2 - Selection Sort
      • 3.2.3 - Bubble Sort
      • 3.2.4 - Shell Sort
    • 3.3 - Sophisticated Sorting
      • 3.3.1 - Quick Sort
      • 3.3.2 - Merge Sort
      • 3.3.3 - Heap Sort
      • 3.3.4 - Radix Sort
      • 3.3.5 - Bucket Sort
      • 3.3.6 - Counting Sort
    • 3.4 - Summary
  • 4 - Graph
    • 4.1 - Intro
    • 4.2 - Graph Traversal
    • 4.3 - Spanning Tree
      • 4.3.1 - Kruskal's algorithm
      • 4.3.2 - Prim's algorithm
      • 4.3.3 - Sollin's algorithm
    • 4.4 - Shortest Path Length
      • 4.4.1 - Dijkstra's algorithm
      • 4.4.2 - Bellman-Ford algorithm
      • 4.4.3 - Floyd-Warshall algorithm
    • 4.5 - AOV Network
    • 4.6 - AOE Network
    • 4.7 - Others
Powered by GitBook
On this page
  • 1. 介紹
  • 2. 基本操作
  1. 1 - Stack & Queue

1.2 - Queue

Introduction of Queue(佇列的基本介紹及應用)

Previous1.1 - StackNext1.3 - Stack and Queue

Last updated 6 years ago

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

  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

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

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

2.4 以Circular Array來表示佇列的基本操作。

示意圖:

特點:

  • 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

2.5 加上tag改善2.3的空間效率

在這裡使用變數tag來記錄佇列是空或是滿的狀態。

示意圖:

  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_linklist.c
https://github.com/gary30404/Data-Structure/blob/master/1/1.2/queue_in_circular_linklist.c
https://github.com/gary30404/Data-Structure/blob/master/1/1.2/queue_in_array.c
https://github.com/gary30404/Data-Structure/blob/master/1/1.2/queue_in_circular_array1.c
https://github.com/gary30404/Data-Structure/blob/master/1/1.2/queue_in_circular_array2.c