首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C 語言單鏈表核心操作完整實現:創建、遍歷、插入、刪除、查找、排序、反轉

     編輯:關於C語言

數據結構定義


typedef struct Node {
    int data;
    struct Node *next;
} Node, *PNode;

核心操作函數庫

1. 創建鏈表 (尾插法)


PNode create_list(void) {
    PNode head = (PNode)malloc(sizeof(Node));
    if (!head) return NULL;
    head->next = NULL;
    
    PNode tail = head;
    int val;
    while (scanf("%d", &val) == 1 && val != -1) { // -1 結束標誌
        PNode node = (PNode)malloc(sizeof(Node));
        if (!node) break;
        node->data = val;
        node->next = NULL;
        tail->next = node;
        tail = node;
    }
    return head; // 返回虛擬頭節點
}

2. 遍歷打印


void print_list(PNode head) {
    PNode cur = head->next;
    while (cur) {
        printf("%d -> ", cur->data);
        cur = cur->next;
    }
    printf("NULL\n");
}

3. 指定位置插入 (0-based 索引,頭節點後為第 0 位)


bool insert_at(PNode head, int index, int value) {
    PNode prev = head;
    for (int i = 0; i < index && prev; i++)
        prev = prev->next;
    if (!prev) return false; // 索引越界
    
    PNode node = (PNode)malloc(sizeof(Node));
    if (!node) return false;
    node->data = value;
    node->next = prev->next;
    prev->next = node;
    return true;
}

4. 按值刪除首個匹配節點


bool delete_val(PNode head, int value) {
    PNode prev = head;
    PNode cur = head->next;
    while (cur) {
        if (cur->data == value) {
            prev->next = cur->next;
            free(cur);
            return true;
        }
        prev = cur;
        cur = cur->next;
    }
    return false; // 未找到
}

5. 查找節點 (返回指針)


PNode find_node(PNode head, int value) {
    PNode cur = head->next;
    while (cur) {
        if (cur->data == value) return cur;
        cur = cur->next;
    }
    return NULL;
}

6. 獲取長度


int list_length(PNode head) {
    int len = 0;
    PNode cur = head->next;
    while (cur) { len++; cur = cur->next; }
    return len;
}

7. 冒泡排序 (數據域交換,非指針重鏈)


void bubble_sort(PNode head) {
    for (PNode i = head->next; i; i = i->next) {
        for (PNode j = i->next; j; j = j->next) {
            if (i->data > j->data) {
                int tmp = i->data;
                i->data = j->data;
                j->data = tmp;
            }
        }
    }
}

8. 就地反轉 (三指針法,O(1) 空間)


void reverse_list(PNode head) {
    PNode prev = NULL;
    PNode cur = head->next;
    head->next = NULL; // 原鏈表置空
    
    while (cur) {
        PNode next = cur->next;
        cur->next = prev;
        prev = cur;
        cur = next;
    }
    head->next = prev; // 新頭接回虛擬頭節點
}

完整測試主程式


int main() {
    PNode list = create_list(); // 輸入: 3 1 4 1 5 9 -1
    printf("原始: "); print_list(list); // 3->1->4->1->5->9
    
    insert_at(list, 2, 99); // 第2位插入99
    printf("插入後: "); print_list(list); // 3->1->99->4->1->5->9
    
    delete_val(list, 1); // 刪除第一個1
    printf("刪除1: "); print_list(list); // 3->99->4->1->5->9
    
    bubble_sort(list);
    printf("排序後: "); print_list(list); // 1->3->4->5->9->99
    
    reverse_list(list);
    printf("反轉後: "); print_list(list); // 99->9->5->4->3->1
    
    // 釋放內存
    PNode cur = list->next;
    while (cur) {
        PNode tmp = cur;
        cur = cur->next;
        free(tmp);
    }
    free(list);
    return 0;
}

進階話題

主題關鍵點
雙向鏈表增加 prev 指針,支援 O(1) 反向遍歷、任意節點刪除
循環鏈表尾節點 next 指向頭,適用於循環調度、Josephus 問題
跳表多層索引層,O(log n) 查找/插入/刪除,Redis 有序集合底層
內存池優化預分配節點塊,避免頻繁 malloc/free 碎片與開銷
無鎖並發CAS 原子操作實現 Lock-Free 鏈表,高性能佇列/棧

常見錯誤避坑

  1. 虛擬頭節點簡化邊界:統一處理「插入頭部/刪除首節點」特殊情況
  2. free 後指針置 NULL:防野指針二次釋放
  3. 遍歷時修改結構需謹慎:保存 next 再操作 cur
  4. 遞歸操作棧溢出風險:長鏈表用迭代
  5. 排序選擇:數據域交換簡單但對大結構體昂貴;指針重鏈通用但複雜
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved