連結串列是一種靈活的資料結構,適合用於需要頻繁插入和刪除操作的場景,但在需要快速隨機訪問的情況下,陣列或其它資料結構更為合適。
特點
- 動態大小
連結串列可以根據需要動態增長或縮小,不需要事先定義大小。
- 非連續儲存
連結串列中的節點在記憶體中不必連續儲存,每個節點透過指標連線。
- 插入和刪除效率高
在連結串列中插入或刪除節點的時間複雜度為 O(1),只需調整指標即可,而在陣列中可能需要移動大量元素,時間複雜度為 O(n)。
- 訪問效率低
連結串列的隨機訪問效率較低,要訪問某個節點需要從頭遍歷,時間複雜度為 O(n)。
適用場景
- 實現佇列和棧
連結串列可以方便地實現佇列(FIFO)和棧(LIFO)等資料結構,因為它們需要頻繁的插入和刪除操作。
- 動態資料儲存
當資料量不確定且需要頻繁變化時,連結串列是一種合適的選擇,例如實現動態陣列的替代品。
- 圖和樹的實現
連結串列可用於表示圖的鄰接表和樹的節點結構,方便儲存和遍歷。
- 記憶體管理
在需要頻繁分配和釋放記憶體的應用中,連結串列可以有效管理記憶體,避免記憶體碎片。
使用示例
透過連結串列的結點來表示棧中的元素。入棧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;
}