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

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

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

特點

  1. 動態大小

連結串列可以根據需要動態增長或縮小,不需要事先定義大小。

  1. 非連續儲存

連結串列中的節點在記憶體中不必連續儲存,每個節點透過指標連線。

  1. 插入和刪除效率高

在連結串列中插入或刪除節點的時間複雜度為 O(1),只需調整指標即可,而在陣列中可能需要移動大量元素,時間複雜度為 O(n)。

  1. 訪問效率低

連結串列的隨機訪問效率較低,要訪問某個節點需要從頭遍歷,時間複雜度為 O(n)。

適用場景

  1. 實現佇列和棧

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

  1. 動態資料儲存

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

  1. 圖和樹的實現

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

  1. 記憶體管理

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

使用示例

透過連結串列的結點來表示棧中的元素。入棧push操作將新元素新增到連結串列的頭部,出棧pop操作則移除連結串列的頭部元素。實現了一個後進先出(LIFO)的棧結構。

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

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

// 定義棧結構
typedef struct Stack {
    Node *top;
} Stack;

// 初始化棧
void initStack(Stack *stack) {
    stack->top = NULL;
}

// 檢查棧是否為空
int isEmpty(Stack *stack) {
    return stack->top == NULL;
}

// 入棧操作
void push(Stack *stack, int value) {
    Node *newNode = (Node *)malloc(sizeof(Node));
    newNode->data = value;
    newNode->next = stack->top;
    stack->top = newNode;
}

// 出棧操作
int pop(Stack *stack) {
    if (isEmpty(stack)) {
        printf("Stack is empty.\n");
        return -1;
    }
    Node *temp = stack->top;
    int value = temp->data;
    stack->top = stack->top->next;
    free(temp);
    return value;
}

// 釋放棧記憶體
void freeStack(Stack *stack) {
    while (!isEmpty(stack)) {
        pop(stack);
    }
}

int main() {
    Stack stack;
    initStack(&stack);
    
    push(&stack, 10);
    push(&stack, 20);
    push(&stack, 30);

    printf("Popped: %d\n", pop(&stack));
    printf("Popped: %d\n", pop(&stack));
    printf("Popped: %d\n", pop(&stack));
    freeStack(&stack);

    return 0;
}

相關文章