FreeRTOS源码解析(单向链表)

1.链表基础知识点

1.1链表的基础结构

什么是链表?

链表是一种线性数据结构,每个元素(节点)包含两个部分:

  • 数据(data)
  • 指向下一个节点的指针(next)
typedef struct node
{
	int data;
	struct node* PNext;
}Node;

链表不使用连续的内存空间,适合频繁插入/删除的场景。

单向链表

每个节点只包含指向

下一个

节点的指针

双向链表

每个节点包含指向

上一个

下一个

节点的指针

循环链表

最后一个节点指向头节点,形成环状结构

双向循环链表

双向链表 + 尾节点的

next

指向头节点,头节点的

prev

指向尾节点

1.2链表添加节点

尾部添加:

通过malloc函数创建节点,节点的地址不连续,通过PNext指针指向下一个节点。

HeadNode
  ↓
┌───────────┐     ┌───────────┐     ┌───────────┐     ┌──────┐
│ data:  0  │ →→→ │ data: 10  │ →→→ │ data: 20  │ →→→ │ NULL │
│ PNext: *  │     │ PNext: *  │     │ PNext: *  │     └──────┘
└───────────┘     └───────────┘     └───────────┘


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

typedef struct node
{
    int data;               // 节点存放的数据
    struct node* PNext;     // 指向下一个节点的指针
} Node;

// 初始化链表头结点
void Init_List(Node* ListHead)
{
    ListHead->data = 0;     // 头结点不存放实际数据
    ListHead->PNext = NULL; // 初始时没有后继节点
}

// 向链表尾部添加节点
int Add(Node* ListHead, int data)
{
    Node* PNode = (Node*)malloc(sizeof(Node));  // 申请新节点内存
    if (PNode == NULL)  // 内存申请失败
    {
        return -1;
    }
    PNode->data = data;     // 设置数据域
    PNode->PNext = NULL;    // 新节点的下一个为空

    Node* PTemp = ListHead;
    while (PTemp->PNext != NULL) // 遍历到最后一个节点
    {
        PTemp = PTemp->PNext;
    }
    PTemp->PNext = PNode;   // 新节点接到链表尾部

    return 0;
}

// 遍历链表并打印所有节点数据
void Traverse_List(Node* ListHead)
{
    Node* PTemp = ListHead->PNext;  // 从头结点的下一个开始
    while (PTemp != NULL)
    {
        printf("%d -> ", PTemp->data);  // 打印节点数据
        PTemp = PTemp->PNext;           // 移动到下一个节点
    }
    printf("NULL\n");  // 表示链表结束
}


int main(void)
{
    Node HeadNode;
    Init_List(&HeadNode);

    // 添加几个节点
    Add(&HeadNode, 10);
    Add(&HeadNode, 20);
    Add(&HeadNode, 30);

    // 遍历链表
    printf("链表内容: ");
    Traverse_List(&HeadNode);

    // 删除链表
    Delete_List(&HeadNode);
    printf("删除链表后: ");
    Traverse_List(&HeadNode);

    return 0;
}


1.3链表删除节点(删除指定下标的节点)

根据下标删除链表节点的本质就是:找到目标节点的前驱节点 → 修改前驱指针跳过目标节点 → 释放目标节点内存。

删除前:

HeadNode
  ↓
┌───────────┐     ┌───────────┐     ┌───────────┐     ┌───────────┐     ┌──────┐
│ data:  0  │ →→→ │ data: 10  │ →→→ │ data: 20  │ →→→ │ data: 30  │ →→→ │ NULL │
│ PNext: *  │     │

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

嵌入式面试八股文全集 文章被收录于专栏

这是一个全面的嵌入式面试专栏。主要内容将包括:操作系统(进程管理、内存管理、文件系统等)、嵌入式系统(启动流程、驱动开发、中断管理等)、网络通信(TCP/IP协议栈、Socket编程等)、开发工具(交叉编译、调试工具等)以及实际项目经验分享。专栏将采用理论结合实践的方式,每个知识点都会附带相关的面试真题和答案解析。

全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务