C语言链表

数据结构与算法


前言

手写C语言链表

代码详解:

  1. 结构体 Node

    • int data:用于存储节点中的数据。
    • struct Node* next:指向下一个节点的指针。这是链表的核心,通过指针将各个节点串联起来。
  2. 指针的使用

    • 在 C 语言中,指针是链表实现的核心,因为链表中的节点是分散在内存中的,指针用于将它们连接起来。

    • struct Node** head:在插入和删除操作中,使用双重指针(**head)的原因是,我们可能需要修改头指针本身。双重指针允许我们在函数中改变原始的头指针。

      c
      
      
      复制代码
      insertAtHead(struct Node** head, int data);
      

      通过 *head = newNode; 语句,我们可以将头指针指向新的节点,更新链表的头部。

  3. createNode 函数

    • 这是创建新节点的函数,通过 malloc 函数动态分配内存,确保链表节点在内存中正确分配。
    c
    
    
    复制代码
    struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
    
    • 动态分配内存后,我们将数据存储在节点中,并将 next 指针初始化为 NULL,因为新节点默认不指向任何后继节点。
  4. insertAtHead 函数

    • 该函数用于在链表头部插入新节点。通过 newNode->next = *head;,我们将新节点的 next 指针指向当前的头节点,然后通过 *head = newNode; 将头指针指向新的节点。
  5. deleteNode 函数

    • 该函数用于从链表中删除某个值对应的节点。如果要删除的节点是头节点,我们只需将头指针指向下一个节点;否则,我们需要找到要删除节点的前一个节点,并调整指针跳过要删除的节点。
  6. printList 函数

    • 该函数通过遍历链表,将每个节点的数据打印出来。使用临时指针 temp 从头节点开始,逐步遍历每个节点,直到 tempNULL(链表的末尾)。
  7. freeList 函数

    • 这是释放链表内存的函数,避免内存泄漏。在这里,我们通过逐个释放节点来确保链表所占用的内存被完全释放。
    c
    
    
    复制代码
    free(temp);
    
    • 每次释放一个节点后,我们将头指针移动到下一个节点,直到整个链表被释放完毕。

亮点:

  1. 内存管理:确保所有分配的内存(malloc)在不使用时通过 free 函数释放,避免内存泄漏。
  2. 双重指针的使用:通过使用 Node** 来操作头指针,确保能够修改原始头指针的值,尤其是在插入和删除操作中。
  3. 代码的可读性和性能:使用简洁的逻辑和遍历方式,保证操作链表时的效率和清晰度。

提示:以下是本篇文章正文内容,下面案例可供参考

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

// 定义链表节点结构体
struct Node {
    int data;            // 存储数据
    struct Node* next;   // 指向下一个节点的指针
};

// 创建新节点
struct Node* createNode(int data);

// 头部插入节点
void insertAtHead(struct Node** head, int data);

// 在链表中删除某个值的节点
void deleteNode(struct Node** head, int key);

// 打印链表中的所有节点
void printList(struct Node* head);

// 释放链表占用的内存
void freeList(struct Node** head);

// 主函数
int main() {
    struct Node* head = NULL;  // 初始化链表为空

    // 向链表头部插入一些数据
    insertAtHead(&head, 10);
    insertAtHead(&head, 20);
    insertAtHead(&head, 30);
    insertAtHead(&head, 40);

    // 打印链表
    printf("链表内容: ");
    printList(head);

    // 删除值为20的节点
    printf("删除节点值为20后的链表: ");
    deleteNode(&head, 20);
    printList(head);

    // 释放链表内存
    freeList(&head);

    return 0;
}

// 创建新节点
struct Node* createNode(int data) {
    struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
    if (!newNode) {
        printf("内存分配失败\n");
        exit(1);  // 终止程序
    }
    newNode->data = data;    // 将数据存储到节点中
    newNode->next = NULL;    // 初始化为无后继节点
    return newNode;
}

// 头部插入节点
void insertAtHead(struct Node** head, int data) {
    struct Node* newNode = createNode(data);  // 创建新节点
    newNode->next = *head;                    // 将新节点的next指针指向当前的头节点
    *head = newNode;                          // 更新头指针,使之指向新节点
}

// 删除链表中某个值的节点
void deleteNode(struct Node** head, int key) {
    struct Node* temp = *head;  // 用于遍历链表的临时指针
    struct Node* prev = NULL;   // 用于保存前驱节点的指针

    // 如果头节点就是要删除的节点
    if (temp != NULL && temp->data == key) {
        *head = temp->next;  // 将头指针指向第二个节点
        free(temp);          // 释放头节点内存
        return;
    }

    // 查找要删除的节点,同时保持前驱节点的记录
    while (temp != NULL && temp->data != key) {
        prev = temp;          // 保存当前节点作为前驱节点
        temp = temp->next;    // 指向下一个节点
    }

    // 如果没有找到要删除的节点
    if (temp == NULL) return;

    // 前驱节点的 next 指向待删除节点的 next,跳过待删除节点
    prev->next = temp->next;
    free(temp);  // 释放内存
}

// 打印链表中的所有节点
void printList(struct Node* head) {
    struct Node* temp = head;  // 临时指针用于遍历链表
    while (temp != NULL) {
        printf("%d -> ", temp->data);
        temp = temp->next;  // 移动到下一个节点
    }
    printf("NULL\n");
}

// 释放链表占用的内存
void freeList(struct Node** head) {
    struct Node* temp;
    while (*head != NULL) {
        temp = *head;         // 保存当前头节点
        *head = (*head)->next;  // 将头指针指向下一个节点
        free(temp);           // 释放当前节点内存
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值