数据结构-单链表模板实现-C语言版

《单链表实现模板-C语言版》—— 从零构建你的“数据火车”


引言

链表是数据结构中的“火车”,每节车厢(节点)通过“连接器”(指针)串联。本文将用C语言手把手教你搭建一列单链表火车,实现增删改查等核心操作,并附完整可运行代码!


一、链表结构设计

1. 节点结构体

typedef struct ListNode {
    eleType data;          // 车厢装载的货物(数据)
    struct ListNode* next; // 连接下一节车厢的挂钩(指针)
} ListNode;
  • data:存储数据(如intchar等)
  • next:指向下一个节点的指针(若为末尾节点,则指向NULL

2. 链表结构体

typedef struct LinkedList {
    ListNode* head; // 火车头(头节点指针)
    size_t size;    // 车厢总数(链表长度)
} LinkedList;
  • head:指向第一个节点的指针(空链表时为NULL
  • size:记录链表长度,避免频繁遍历计数

二、核心功能实现

1. 创建链表(初始化火车)

void LinkedListCreate(LinkedList* list) {
    list->head = NULL; // 初始时火车头不挂车厢
    list->size = 0;    // 车厢数为0
}
  • 初始化空链表,相当于建造一个“空火车头”

2. 插入节点(添加新车厢)

void LinkedListInsert(LinkedList* list, int i, eleType value) {
    // 判断插入位置合法性
    if (i < 0 || i > list->size) {
        printf("Invalid index\n");
        return;
    }
    
    // 创建新节点(新车厢)
    ListNode* newNode = (ListNode*)malloc(sizeof(ListNode));
    newNode->data = value;
    
    if (i == 0) {  // 插入到火车头部
        newNode->next = list->head; // 新车厢连接原第一节
        list->head = newNode;       // 火车头指向新车厢
    } else {       // 插入中间或尾部
        ListNode* current = list->head;
        for (int j = 0; j < i-1; j++) { // 找到第i-1节车厢
            current = current->next;
        }
        newNode->next = current->next; // 新车厢挂钩后续车厢
        current->next = newNode;       // 前车厢挂钩新车厢
    }
    list->size++; // 车厢总数+1
}
  • 头插法:直接修改火车头指针
  • 中间/尾插法:找到前一节车厢,调整指针连接

3. 删除节点(卸下车厢)

void LinkedListRemove(LinkedList* list, int i) {
    // 判断删除位置合法性
    if (i < 0 || i >= list->size) {
        printf("Invalid index\n");
        return;
    }
    
    if (i == 0) {  // 删除火车头后的第一节
        ListNode* temp = list->head;
        list->head = list->head->next; // 火车头指向第二节
        free(temp); // 释放原第一节内存
    } else {       // 删除中间或尾部车厢
        ListNode* current = list->head;
        for (int j = 0; j < i-1; j++) { // 找到第i-1节车厢
            current = current->next;
        }
        ListNode* temp = current->next; 
        current->next = temp->next; // 前车厢挂钩后车厢
        free(temp); // 释放目标车厢内存
    }
    list->size--; // 车厢总数-1
}
  • 内存释放:必须释放被删除节点的内存,防止内存泄漏

4. 查找与修改(查找货物/更换货物)

按值查找
ListNode* LinkedListFind(LinkedList* list, eleType value) {
    ListNode* current = list->head;
    while (current) {
        if (current->data == value) {
            return current; // 找到目标车厢
        }
        current = current->next;
    }
    return NULL; // 未找到
}
按索引修改
void LinkedListUpdate(LinkedList* list, int i, eleType value) {
    ListNode* node = LinkedListGet(list, i); // 获取第i节车厢
    if (node) {
        node->data = value; // 更换货物
    }
}

5. 打印链表(展示火车全貌)

void LinkedListPrint(LinkedList* list) {
    ListNode* current = list->head;
    while (current) {
        printf("%d -> ", current->data);
        current = current->next;
    }
    printf("NULL\n"); // 末尾标记
}
  • 遍历输出每个节点的数据,末尾指向NULL

三、实战演示

主函数测试

int main() {
    LinkedList list;
    LinkedListCreate(&list); // 初始化空链表
    
    // 插入车厢
    LinkedListInsert(&list, 0, 10); // 头插10
    LinkedListInsert(&list, 1, 20); // 第1位插20
    LinkedListInsert(&list, 2, 30); // 第2位插30
    LinkedListInsert(&list, 3, 40); // 第3位插40
    printf("初始链表:");
    LinkedListPrint(&list); // 10 -> 20 -> 30 -> 40 -> NULL
    
    LinkedListRemove(&list, 1);     // 删除第1节车厢(20)
    LinkedListUpdate(&list, 0, 100); // 修改第0节为100
    
    printf("最终链表:");
    LinkedListPrint(&list); // 100 -> 30 -> 40 -> NULL
    
    LinkedListDestroy(&list); // 销毁链表(拆解火车)
    return 0;
}

四、复杂度分析

  • 插入/删除
    • 头部操作:O(1)
    • 中间/尾部操作:O(n)(需遍历到目标位置)
  • 查找/修改:O(n)(最坏情况遍历整个链表)

五、单链表的优缺点

优点

  1. 动态内存分配:无需预先知道数据量大小
  2. 高效插入/删除:头部操作时间复杂度为O(1)

缺点

  1. 随机访问低效:必须从头遍历到目标位置
  2. 内存开销:每个节点需额外存储指针

六、扩展思考

  1. 双向链表:如何实现“双向行驶”(前驱和后继指针)?
  2. 循环链表:如何让末尾节点指向头节点形成“环形铁路”?
  3. 优化查找:如何通过哈希表或跳表加速查找?

掌握单链表实现,就解锁了数据结构的第一把钥匙!后续可继续挑战栈、队列、树等高级结构。

你可能感兴趣的:(数据结构基础,数据结构,c语言,网络)