C链表的一些基础知识

一、链表的基本概念

链表是一种常见的线性数据结构,它由一系列节点组成,每个节点包含数据部分和指向下一个节点的指针(单链表情况)。通过指针将各个节点连接起来,与数组不同,链表在内存中的存储不是连续的,其优点是可以灵活地进行插入、删除操作,无需像数组那样移动大量元素。

二、单链表的实现

  1. 定义节点结构体

    // 定义单链表节点结构体
    typedef struct ListNode {
    int data; // 数据域,这里以整型数据为例,可根据需求修改类型
    struct ListNode *next; // 指针域,指向下一个节点
    } ListNode;

  2. 创建链表节点函数

    // 创建一个新的链表节点
    ListNode *createNode(int value) {
    ListNode *newNode = (ListNode *)malloc(sizeof(ListNode));
    if (newNode == NULL) {
    printf("内存分配失败!\n");
    return NULL;
    }
    newNode->data = value;
    newNode->next = NULL;
    return newNode;
    }

  3. 插入节点(尾插法为例)

    // 尾插法向链表插入节点
    void insertTail(ListNode **head, int value) {
    ListNode *newNode = createNode(value);
    if (*head == NULL) {
    *head = newNode;
    } else {
    ListNode *temp = *head;
    while (temp->next!= NULL) {
    temp = temp->next;
    }
    temp->next = newNode;
    }
    }

  4. 遍历链表函数

    // 遍历链表并输出节点数据
    void traverseList(ListNode *head) {
    ListNode *current = head;
    while (current!= NULL) {
    printf("%d ", current->data);
    current = current->next;
    }
    printf("\n");
    }

  5. 释放链表内存函数

    // 释放链表占用的内存
    void freeList(ListNode *head) {
    ListNode *current = head;
    ListNode *next;
    while (current!= NULL) {
    next = current->next;
    free(current);
    current = next;
    }
    }

三、双链表的实现

  1. 定义双链表节点结构体

    // 定义双链表节点结构体
    typedef struct DoublyListNode {
    int data;
    struct DoublyListNode *prev; // 指向前一个节点的指针
    struct DoublyListNode *next; // 指向后一个节点的指针
    } DoublyListNode;

  2. 创建双链表节点函数

    // 创建双链表节点
    DoublyListNode *createDoublyNode(int value) {
    DoublyListNode *newNode = (DoublyListNode *)malloc(sizeof(DoublyListNode));
    if (newNode == NULL) {
    printf("内存分配失败!\n");
    return NULL;
    }
    newNode->data = value;
    newNode->prev = NULL;
    newNode->next = NULL;
    return newNode;
    }

  3. 插入节点(尾插法为例)

    // 尾插法向双链表插入节点
    void insertTailDoubly(DoublyListNode **head, int value) {
    DoublyListNode *newNode = createDoublyNode(value);
    if (*head == NULL) {
    *head = newNode;
    } else {
    DoublyListNode *temp = *head;
    while (temp->next!= NULL) {
    temp = temp->next;
    }
    temp->next = newNode;
    newNode->prev = temp;
    }
    }

  4. 遍历双链表(正向)函数

    // 正向遍历双链表并输出节点数据
    void traverseDoublyListForward(DoublyListNode *head) {
    DoublyListNode *current = head;
    while (current!= NULL) {
    printf("%d ", current->data);
    current = current->next;
    }
    printf("\n");
    }

  5. 遍历双链表(反向)函数

    // 反向遍历双链表并输出节点数据
    void traverseDoublyListBackward(DoublyListNode *head) {
    DoublyListNode *current = head;
    if (current == NULL) return;
    while (current->next!= NULL) {
    current = current->next;
    }
    while (current!= NULL) {
    printf("%d ", current->data);
    current = current->prev;
    }
    printf("\n");
    }

  6. 释放双链表内存函数

    // 释放双链表占用的内存
    void freeDoublyList(DoublyListNode *head) {
    DoublyListNode *current = head;
    DoublyListNode *next;
    while (current!= NULL) {
    next = current->next;
    free(current);
    current = next;
    }
    }

四、循环链表

  1. 循环单链表
    循环单链表与普通单链表的区别在于,其最后一个节点的指针不是指向 NULL,而是指向链表的头节点,形成一个环形结构。在实现插入、遍历等操作时,需要注意循环的终止条件有所不同,例如遍历循环单链表时,判断节点是否回到头节点来结束循环。
  2. 循环双链表
    循环双链表中,头节点的 prev 指针指向尾节点,尾节点的 next 指针指向头节点,构成双向循环结构。其操作函数在处理边界情况和指针修改时要考虑这种循环特性,比如插入节点时要正确更新节点间的双向指针关系。

五、链表的常用操作及函数总结

  • 创建节点:用于生成新的链表节点,分配内存并初始化数据和指针域。
  • 插入节点:可以有头插法、尾插法、按位置插入等多种方式,调整链表节点间的指针连接关系来插入新节点。
  • 删除节点:根据节点的值或者位置等条件,找到要删除的节点,并妥善处理其前后节点的指针连接,释放对应节点内存。
  • 遍历链表:按顺序访问链表中的每个节点,输出节点数据或者进行其他需要逐个节点处理的操作,单链表通常是单向遍历,双链表可实现双向遍历。
  • 查找节点:依据给定的条件(如节点值等)在链表中查找满足条件的节点,返回节点指针或者相关索引等信息。

六、链表的应用场景

  • 动态数据存储:当需要频繁地插入、删除元素,且元素数量不确定时,链表比数组更合适,比如实现一个简单的任务队列管理系统。
  • 多项式表示与运算:可以用链表来存储多项式的各项系数和指数,方便进行多项式的加法、乘法等运算。
  • 操作系统中的进程管理:用于管理进程控制块(PCB)链表,方便对进程进行调度、插入新进程、结束进程等操作。

总之,链表在 C 语言编程中是非常重要的数据结构,熟练掌握其实现和各种操作函数,能帮助更好地解决很多实际编程问题。

相关推荐
边境悍匪2 分钟前
蜗牛学苑 Java 智能体学习 Day39|SpringAI 会话存储、Function‑Call 工具调用、MCP 思维导图复盘
java·开发语言·spring boot·学习·阿里云
万物智能信息科技16 分钟前
RK3568 的多路显示移植—【万物智能之开源鸿蒙OpenHarmony系统实战开发系列教程】
linux·开发语言·华为·开源·harmonyos
蓝悦无人机29 分钟前
Qt Design Studio(QDS)4.8.2项目文件结构详解
开发语言·qt·qt creator·qds·项目文件结构·qtc
yxlalm44 分钟前
4.java秒杀项目第四课-后端商品后台接口
java·开发语言
孙启超1 小时前
【AI开发之Rust】第 1 课:认识 Rust 与开发环境 —— 装好工具链,跑通第一个程序
开发语言·人工智能·后端·ai·rust·安全架构
君顾11 小时前
家政派单小程序源码开发实战:从零搭建到上线全流程指南
java·开发语言·家政派单
番茄灭世神2 小时前
汇顶模拟前端GH3220使用备忘录
c语言·单片机·传感器·模拟芯片·电生理信号处理
我是唐青枫2 小时前
C#.NET PInvoke 深入解析:封送、内存布局与原生互操作实战
开发语言·c#·.net
程序猿编码2 小时前
纯C++轻量计算机视觉推理引擎:基于GGML的端侧CV模型部署技术全解析
开发语言·c++·计算机视觉·大模型·transformer
SEO_juper3 小时前
外贸多语言站最隐蔽的流量杀手:hreflang 错了,谷歌把德语页推给美国人(附审计脚本)
开发语言·前端·python·seo·独立站·谷歌优化