实现单链表的头插法和尾插法是构建链表的两种基本方式,分别用于将新结点插入到链表头部或尾部

  1. 单链表的删除操作(删除 p 所指结点的后继结点)
    • 步骤:
      ① 用临时指针 q 指向待删除的后继结点:q = p->next;
      ② 修改 p 的指针,跳过待删除结点:p->next = p->next->next;
      ③ 释放 q 所指结点的内存:free(q);
    • 注意:必须确保 p 不为 NULLp->next 不为 NULL,否则无法删除后继。
void DeleteAfter(ListNode* p) {
    if (p == NULL || p->next == NULL) return; // 防止空指针
    ListNode* q = p->next;
    p->next = q->next;
    free(q);
}
  1. 单链表的查找运算(函数 Find_List)
    • 功能:在带头结点的单链表中查找第 k 个元素(从1开始计数),若存在则返回该结点指针,否则返回 NULL
    • 核心逻辑:
      ① 从头结点的下一个结点(第一个实际元素)开始遍历
      ② 使用计数器 i 记录当前是第几个元素
      ③ 当 i == k 或链表结束时停止循环
      ④ 返回对应结点或 NULL
ListNode* Find_List(ListNode* L, int k) {
    if (L == NULL || k < 1) return NULL;
    ListNode* p = L->next; // 第一个元素结点
    int i = 1;
    while (p != NULL && i < k) {
        p = p->next;
        i++;
    }
    return p; // 若找到第k个则返回p,否则返回NULL
}
  1. 单链表的插入运算(函数 Insert_List)
    • 功能:将新元素 newElem 插入到第 k 个元素之前(即插入后成为新的第 k 个元素)
    • 成功返回 0,失败返回 -1
    • 核心逻辑:
      ① 若 k == 1,前驱为头结点 L
      ② 否则查找第 k-1 个结点 p
      ③ 若 p 存在,则创建新结点 s,将其插入到 p 之后
      ④ 新结点指向原 p->next,再更新 p->next 指向 s
int Insert_List(ListNode* L, int k, ElemType newElem) {
    if (L == NULL || k < 1) return -1;
    ListNode* p = L;
    // 查找第k-1个结点(若k=1,则直接使用头结点)
    for (int i = 1; i < k; i++) {
        p = p->next;
        if (p == NULL) return -1; // 第k-1个结点不存在
    }
    // 创建新结点
    ListNode* s = (ListNode*)malloc(sizeof(ListNode));
    if (s == NULL) return -1; // 内存分配失败
    s->data = newElem;
    s->next = p->next;
    p->next = s;
    return 0; // 插入成功
}

实现单链表的头插法和尾插法是构建链表的两种基本方式,分别用于将新结点插入到链表头部或尾部。


1. 头插法(Head Insertion)

  • 特点:每次将新结点插入到链表的最前端(即头结点之后),最终链表中元素的顺序与输入顺序相反
  • 适用场景:不关心元素顺序时快速建表,如栈式结构。
  • 步骤
    ① 创建新结点 s
    ② 将 s->next 指向原第一个元素(即 L->next
    ③ 更新头结点的指针:L->next = s
void HeadInsert(ListNode* L) {
    ElemType x;
    ListNode* s;
    // 假设以输入 -1 结束
    while (scanf("%d", &x) && x != -1) {
        s = (ListNode*)malloc(sizeof(ListNode));
        if (s == NULL) return; // 内存分配失败
        s->data = x;
        s->next = L->next;   // 新结点指向原第一个结点
        L->next = s;         // 头结点指向新结点
    }
}

2. 尾插法(Tail Insertion)

  • 特点:每次将新结点插入到链表的末尾,保持元素的输入顺序。
  • 适用场景:需要保持数据原始顺序时使用,如队列式结构。
  • 步骤
    ① 创建新结点 s
    ② 使用尾指针 rear 记录链表最后一个结点
    ③ 将 rear->next 指向 s,然后更新 rear = s
void TailInsert(ListNode* L) {
    ListNode *s, *rear = L; // rear 始终指向尾结点
    ElemType x;
    // 假设以输入 -1 结束
    while (scanf("%d", &x) && x != -1) {
        s = (ListNode*)malloc(sizeof(ListNode));
        if (s == NULL) return; // 内存分配失败
        s->data = x;
        s->next = NULL;
        rear->next = s;   // 当前尾结点指向新结点
        rear = s;         // 更新尾指针
    }
}

完整示例初始化(带头结点)

ListNode* InitList() {
    ListNode* L = (ListNode*)malloc(sizeof(ListNode));
    L->next = NULL;
    return L;
}

在这里插入图片描述

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Bol5261

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值