Skip to main content

Command Palette

Search for a command to run...

Data Structure: Queue

Updated
•4 min read•View as Markdown
K

コツコツやる

Introduction

佇列是一種先進先出的一種資料結構,類似於堆疊,但差別在於佇列刪除的元素是最早加入的元素

但是會發生陣列的前面還有空間,但因為rear已經大於等於n - 1,所以會產生佇列已滿的訊息,因此佇列常常以環狀佇列的方式來表示

Methods

  1. Enqueue:加入資料到佇列裡

  2. Dequeue:刪除front變數所指的值

  3. isEmpty:檢查佇列是否是空的

  4. Peek:取得front變數所指的值

Time Complexity

Operation

Time Complexity

Worst Time Complexity

Space Complexity

Enqueue

O(1)

O(n)

O(1)

Dequeue

O(1)

O(n)

O(1)

Peek

O(1)

O(1)

O(1)

isEmpty

O(1)

O(1)

O(1)

Queue Implementation

Array Implementation of the Queues

佇列的結構定義

Enqueue()

  1. 先判斷佇列是否已滿

  2. 如果還有空間就把rear變數加1

  3. 否則就顯示已滿訊息

Dequeue()

  1. 先判斷佇列是否有資料

  2. 如果有就把front加1來刪除元素

Peek()

判斷是否有資料,否則就顯示最前面的資料

isEmpty()

如果front大於rear,代表佇列是空的,因為一開始front等於0而rear等於-1

完整的程式碼

#include <stdio.h>
#include <stdlib.h>

#define MAX 10   /*定義佇列的大小*/

void enqueueFunction(void);
void dequeueFunction(void);
void listFunction(void);
int isEmpty();
int isFull();
int clear();
int head();
int tail();

int item[MAX];
int front = 0;
int rear = -1;

int main()
{
    char option;
    while (1)
    {
        printf("\n *****************************\n");
        printf("       <1> insert (enqueue)\n");
        printf("       <2> delete (dequeue)\n");
        printf("       <3> list\n");
        printf("       <4> empty\n");
        printf("       <5> full\n");
        printf("       <6> clear\n");
        printf("       <7> peek\n");
        printf("       <8> Tail\n");
        printf("       <9> quit\n");
        printf(" *****************************\n");
        printf(" Please enter your choice...");
        option = getchar();
        switch (option)
        {
        case '1':
            enqueueFunction();
            break;
        case '2':
            dequeueFunction();
            break;
        case '3':
            listFunction();
            break;
        case '4':
            printf("Is queue empty? %s", isEmpty() ? "Yes" : "No");
            break;
        case '5':
            printf("Is queue full? %s", isFull() ? "Yes" : "No (there are 10 elements that can be accomodated)");
            break;
        case '6':
            clear();
            printf("Queue is cleared.");
            break;
        case '7':
            printf("Head: %d", peek());
            break;
        case '8':
            printf("Tail: %d", tail());
            break;
        case '9':
            printf("\n");
            return 0;
        }
        fflush(stdin);
    }
}

void enqueueFunction() {
    if (rear >= MAX - 1)
    {
        printf("\n\nQueue is full!\n");
    }
    else
    {
        rear++;
        printf("\n\n Please enter item to insert: ");
        scanf_s("%d", &item[rear]);
    }
}

void dequeueFunction() {
    if (front > rear)
    {
        printf("\n\n No item, queue is empty!\n");
    }
    else
    {
        printf("\n\n Item %d deleted\n", item[front]);
        front++;
    }
}

void listFunction() {
    int count = 0;

    if (front > rear)
    {
        printf("\n\n No item, queue is empty!\n");
    }
    else
    {
        printf("\n\n  ITEM\n");
        printf(" ------------------\n");
        for (int i = front; i <= rear; i++)
        {
            printf("  %-20d\n", item[i]);
            count++;
        }
        printf(" ------------------\n");
        printf("  Total item: %d\n", count);
    }
}

int isEmpty() {
    if (front > rear)
        return 1;
    else
        return 0;
}

int isFull() {
    if (rear == MAX - 1)
        return 1;
    else
        return 0;
}

int clear() {
    return front = 0, rear = -1;
}

int peek() {
    if (isEmpty()) {
        exit(0);
    }
    else {
        return item[front];
    }
}

int tail() {
    return item[rear];
}

Linked list Implementation of the Queues

佇列的結構定義

Enqueue()

基本上跟陣列的實現是差不多的,只是多了如果是空的話,就把head、rear、front都指向新結點,來代表是佇列的頭節點

Dequeue()

鏈結串列要刪除節點時,只要把head移動到下一個位址就好了

Peek()

isEmpty()

完整的程式碼

#include <stdio.h>
#include <stdlib.h>

typedef struct list
{
    int data;
    struct list* next;
} list;

list* head = NULL;
list* rear = NULL;
list* front = NULL;

int isEmpty()
{
    if (head == NULL)
    {
        return 1;
    }
    return 0;
}

int isFull()
{
    list* temp = (list*)malloc(sizeof(list));
    if (temp == NULL)
    {
        return 1;
    }
    return 0;
}

void enqueue(int data)
{
    if (isFull())
    {
        printf("\nQueue is full\n");
        return;
    }
    if (isEmpty())
    {
        head = (list*)malloc(sizeof(list));
        head->data = data;
        head->next = NULL;
        rear = head;
        front = head;
        return;
    }
    list* temp = (list*)malloc(sizeof(list));
    temp->data = data;
    temp->next = NULL;
    rear->next = temp;
    rear = temp;
}

void dequeue()
{
    int data;
    if (isEmpty())
    {
        printf("\nQueue is empty\n");
        return;
    }
    list* temp = head;
    data = temp->data;
    head = head->next;
    free(temp);
    printf("\n%d deleted from queue\n", data);
}

void display()
{
    list* temp = head;
    if (isEmpty())
    {
        printf("\nQueue is empty\n");
        return;
    }
    printf("\nQueue is: ");
    while (temp != NULL)
    {
        printf("%d ", temp->data);
        temp = temp->next;
    }
    printf("\n");
}

int size()
{
    int count = 0;
    list* temp = head;

    if (isEmpty())
    {
        return count;
    }

    while (temp != NULL)
    {
        count++;
        temp = temp->next;
    }
    return count;
}

int peek()
{
    if (isEmpty())
    {
        printf("\nQueue is empty\n");
        return -1;
    }
    return front->data;
}

int rearElement()
{
    if (isEmpty())
    {
        printf("\nQueue is empty\n");
        return -1;
    }
    return rear->data;
}

int clear() {
    if (isEmpty()) {
        printf("\nThe queue is empty!\n");
        return 0;
    }
    list* current = head;
    list* next = NULL;
    while (current != NULL)
    {
        next = current->next;
        free(current);
        current = next;
    }
    head = front = rear = NULL;
    return isEmpty();
}

int main()
{
    int choice, data, position;
    while (1)
    {
        printf("\n1. Enqueue");
        printf("\n2. Dequeue");
        printf("\n3. Display");
        printf("\n4. Size");
        printf("\n5. Peek");
        printf("\n6. Rear element");
        printf("\n7. Is Empty?");
        printf("\n8. Clear queue");
        printf("\n9. Exit");
        printf("\n\nEnter your choice: ");
        scanf_s("%d", &choice);
        printf("\n");
        switch (choice)
        {
        case 1:
            printf("\nEnter data: ");
            scanf_s("%d", &data);
            enqueue(data);
            break;
        case 2:
            dequeue();
            break;
        case 3:
            display();
            break;
        case 4:
            printf("\nSize of queue is: %d", size());
            break;
        case 5:
            printf("\nFront element of queue is: %d", peek());
            break;
        case 6:
            printf("\nRear element of queue is: %d", rearElement());
            break;
        case 7:
            printf(isEmpty() ? "\nTrue\n" : "\nFalse\n");
            break;
        case 8:
            printf(clear() ? "\nCleared\n" : "\n清除失敗\n");
            break;
        case 9:
            exit(0);
        default:
            printf("\nInvalid choice\n");
        }
        printf("\n");
    }
}

佇列的優點:

  1. 簡單易懂:佇列的操作很簡單,只需要按照先進先出的原則即可。

  2. 操作效能:佇列可以很快地在表的前端進行刪除、在表的後端進行插入等操作。

佇列的缺點:

  1. 佇列大小固定:使用陣列實現佇列時,佇列大小是固定的,如果要擴大佇列的大小需要重新分配空間,這樣會浪費很多時間。

  2. 浪費陣列空間:使用陣列實現佇列時,可能會因為佇列空間不足而無法使用,這些空間無法被重複使用,但是如果佇列空間過大,又會浪費空間。

More from this blog

Binary Tree

樹狀結構的一些專有名詞 一般的樹狀結構擁有以下的特徵: 節點:代表某項資料 根結點:沒有父節點的節點,一顆樹也只能有一個根結點 父節點、子節點:若某個節點連接到下面一個節點,則該節點為父節點,而下面的節點稱為子節點 祖先節點、子孫節點:若某個節點有一條路徑可以通往另一個節點,那就代表該節點為祖先節點 兄弟節點:當它們都是同一個父節點的子節點時則該子節點們互為兄弟節點 樹葉節點:分支度為0的節點 分支度:一個節點有幾個子節點稱為分支度 高度:某節點到距離最遠的樹葉節點的最長路徑...

Jun 12, 20235 min read

Multiple Stacks

Introduction 所謂的多個堆疊,是指在一個陣列裡實現K個堆疊,如下方圖片裡,3個堆疊要平分陣列裡的位址 要實現多個堆疊有兩個方法可以實現 Simple method:將陣列劃分為 n/k Efficient method:節省空間 Implementation Simple method 結構定義 push() 加入時要先判斷該堆疊是否已經到下一個堆疊的bottom了 pop() 刪除時只要判斷同一個堆疊是否相同就好,然後再把該堆疊的top遞減 完整的程式碼 #incl...

May 27, 20235 min read
Multiple Stacks

Doubly Circular Linked List

Introduction 雙向鏈結串列與單向鏈結串列相比,雙向鏈結串列多了一個指向前一個節點的指標 並且最後一個節點會重新指回head節點,head節點也會指向最後一個節點 Methods 以下為雙向鏈結串列常見的操作 Insertion:加入節點 Deletion:刪除節點 Search:查詢該節點是否存在於雙向鏈結串列 Reverse:反轉雙向鏈結串列 Time Complexity OperationTime ComplexityWorst Time ComplexityS...

May 14, 20235 min read
Doubly Circular Linked List

Array、Singly Linked List

Introduction 最基本的資料結構就是由線性排列儲存的,我們可以分成利用陣列或是鏈結串列,這2者的差別在於陣列在記憶體中是連續排列的,而鏈結串列在記憶體中不是連續排列的。 鏈結串列指的是將多個不連續的資料節點,透過指標方式串連起來的資料結構,鏈結串列由多個節點組成,每個節點至少包含資料以及儲存下一個位址的指標 鏈結串列因為可以動態的增加和刪除節點,因此在頻繁需要加入和刪除的時候會很有用,因為當陣列要加入或刪除時,必須要移動節點才不會浪費空間 Dynamic Array #includ...

May 12, 20239 min read
Array、Singly Linked List

kiniku

6 posts