連結串列還會用嗎?用連結串列實現佇列(附演算法原始碼)

Newton爱编程發表於2024-11-23

本文主要介紹一下連結串列的特點和使用場景,並且用C語言基於連結串列實現了佇列(FIFO)。

連結串列是一種靈活的資料結構,適合用於需要頻繁插入和刪除操作的場景,但在需要快速隨機訪問的情況下,陣列或其它資料結構可能更為合適。

特點

  1. 動態大小
    連結串列可以根據需要動態增長或縮小,不需要事先定義大小。
  2. 非連續儲存
    連結串列中的節點在記憶體中不必連續儲存,每個節點透過指標連線。
  3. 插入和刪除效率高
    在連結串列中插入或刪除節點的時間複雜度為 O(1),只需調整指標即可,而在陣列中可能需要移動大量元素,時間複雜度為 O(n)。
  4. 訪問效率低
    連結串列的隨機訪問效率較低,要訪問某個節點需要從頭遍歷,時間複雜度為 O(n)。
    適用場景
  5. 實現佇列和棧

連結串列可以方便地實現佇列(FIFO)和棧(LIFO)等資料結構,因為它們需要頻繁的插入和刪除操作。

  1. 動態資料儲存

當資料量不確定且需要頻繁變化時,連結串列是一種合適的選擇,例如實現動態陣列的替代品。

  1. 圖和樹的實現

連結串列可用於表示圖的鄰接表和樹的節點結構,方便儲存和遍歷。

  1. 記憶體管理

在需要頻繁分配和釋放記憶體的應用中,連結串列可以有效管理記憶體,避免記憶體碎片。

使用示例

下面是使用連結串列實現佇列(FIFO)的 C 語言示例程式碼。包括基本的佇列操作,如入隊(enqueue)、出隊(dequeue)。

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

// 定義連結串列節點
struct Node {
    int data;
    struct Node* next;
};

// 定義佇列結構
struct Queue {
    struct Node* front; // 佇列前端
    struct Node* rear;  // 佇列後端
};

// 建立新的節點
struct Node* createNode(int data) {
    struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
    newNode->data = data;
    newNode->next = NULL;
    return newNode;
}

// 初始化佇列
struct Queue* createQueue() {
    struct Queue* queue = (struct Queue*)malloc(sizeof(struct Queue));
    queue->front = NULL;
    queue->rear = NULL;
    return queue;
}

// 入隊操作
void enqueue(struct Queue* queue, int data) {
    struct Node* newNode = createNode(data);
    if (queue->rear == NULL) {
        // 如果佇列為空,前端和後端都指向新節點
        queue->front = newNode;
        queue->rear = newNode;
    } else {
        // 否則,將新節點新增到佇列後端
        queue->rear->next = newNode;
        queue->rear = newNode;
    }
    printf("%d 入隊\n", data);
}

// 出隊操作
int dequeue(struct Queue* queue) {
    if (queue->front == NULL) {
        printf("佇列為空,無法出隊\n");
        return -1; // 表示佇列為空
    }
    struct Node* temp = queue->front;
    int data = temp->data;
    queue->front = queue->front->next;

    // 如果佇列變為空,更新後端指標
    if (queue->front == NULL) {
        queue->rear = NULL;
    }
    free(temp);
    printf("%d 出隊\n", data);
    return data;
}

// 列印佇列內容
void printQueue(struct Queue* queue) {
    struct Node* current = queue->front;
    if (current == NULL) {
        printf("佇列為空\n");
        return;
    }
    printf("佇列內容: ");
    while (current != NULL) {
        printf("%d ", current->data);
        current = current->next;
    }
    printf("\n");
}

// 主函式
int main() {
    struct Queue* queue = createQueue();

    enqueue(queue, 10);
    enqueue(queue, 20);
    enqueue(queue, 30);
    printQueue(queue);

    dequeue(queue);
    printQueue(queue);

    dequeue(queue);
    printQueue(queue);

    dequeue(queue);
    printQueue(queue);

    dequeue(queue); // 嘗試從空佇列出隊

    // 釋放佇列記憶體(可選)
    free(queue);

    return 0;
}

程式碼邏輯比較清晰,就不做過多解釋了。

相關文章