203.删除链表指定元素

题目

Remove all elements from a linked list of integers that have value val.

Example:

Input:  1->2->6->3->4->5->6, val = 6
Output: 1->2->3->4->5

分析

  • 本题属于典型的链表节点删除题目,使用虚拟头节点可以省去很多特殊的情况单独考虑

代码和注释

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */

struct ListNode* removeElements(struct ListNode* head, int val){
    struct ListNode ret, *p, *q; // 定义虚拟头节点 
    ret.next = head; //虚拟头节点指向真正的头节点
    p = &ret; // 节点指针p指向ret,可以省去对head节点是否为空以及head节点是否为要删除节点的单独考虑
    while(p->next) {
        if (p->next->val == val) {
            q = p->next;
            p->next = q->next;
            free(q);
        } else {
            p = p->next;
        }
    }
    return ret.next;
}
预期输出:第一次操作需选择初始化 请选择所要进行的操作: 1.初始化 2.清空链表 3.链表长度 4.检查链表是否为空 5.遍历链表 6.已知位置读取链表元素 7.查找给定元素链表中的位置 8.链表中插入元素 9.链表删除元素 其他键退出。。。。。 请选择所要进行的操作: 1.初始化 2.清空链表 3.链表长度 4.检查链表是否为空 5.遍历链表 6.已知位置读取链表元素 7.查找给定元素链表中的位置 8.链表中插入元素 9.链表删除元素 其他键退出。。。。。 链表为空 请选择所要进行的操作: 1.初始化 2.清空链表 3.链表长度 4.检查链表是否为空 5.遍历链表 6.已知位置读取链表元素 7.查找给定元素链表中的位置 8.链表中插入元素 9.链表删除元素 其他键退出。。。。。 请输入要插入的元素的位置和其值:. 已插入元素 请选择所要进行的操作: 1.初始化 2.清空链表 3.链表长度 4.检查链表是否为空 5.遍历链表 6.已知位置读取链表元素 7.查找给定元素链表中的位置 8.链表中插入元素 9.链表删除元素 其他键退出。。。。。 请输入要插入的元素的位置和其值:. 已插入元素 请选择所要进行的操作: 1.初始化 2.清空链表 3.链表长度 4.检查链表是否为空 5.遍历链表 6.已知位置读取链表元素 7.查找给定元素链表中的位置 8.链表中插入元素 9.链表删除元素 其他键退出。。。。。 请输入要插入的元素的位置和其值:. 已插入元素 请选择所要进行的操作: 1.初始化 2.清空链表 3.链表长度 4.检查链表是否为空 5.遍历链表 6.已知位置读取链表元素 7.查找给定元素链表中的位置 8.链表中插入元素 9.链表删除元素 其他键退出。。。。。 请输入要插入的元素的位置和其值:. 已插入元素 请选择所要进行的操作: 1.初始化 2.清空链表 3.链表长度 4.检查链表是否为空 5.遍历链表 6.已知位置读取链表元素 7.查找给定元素链表中的位置 8.链表中插入元素 9.链表删除元素 其他键退出。。。。。 链表元素为:5 6 7 8 请选择所要进行的操作: 1.初始化 2.清空链表 3.链表长度 4.检查链表是否为空 5.遍历链表 6.已知位置读取链表元素 7.查找给定元素链表中的位置 8.链表中插入元素 9.链表删除元素 其他键退出。。。。。 链表长度为4 请选择所要进行的操作: 1.初始化 2.清空链表 3.链表长度 4.检查链表是否为空 5.遍历链表 6.已知位置读取链表元素 7.查找给定元素链表中的位置 8.链表中插入元素 9.链表删除元素 其他键退出。。。。。 链表非空 请选择所要进行的操作: 1.初始化 2.清空链表 3.链表长度 4.检查链表是否为空 5.遍历链表 6.已知位置读取链表元素 7.查找给定元素链表中的位置 8.链表中插入元素 9.链表删除元素 其他键退出。。。。。 请输入位置 元素值为 6 请选择所要进行的操作: 1.初始化 2.清空链表 3.链表长度 4.检查链表是否为空 5.遍历链表 6.已知位置读取链表元素 7.查找给定元素链表中的位置 8.链表中插入元素 9.链表删除元素 其他键退出。。。。。 请输入待查找元素链表元素8的位置是:4 请选择所要进行的操作: 1.初始化 2.清空链表 3.链表长度 4.检查链表是否为空 5.遍历链表 6.已知位置读取链表元素 7.查找给定元素链表中的位置 8.链表中插入元素 9.链表删除元素 其他键退出。。。。。 输入要删除元素的位置: 已删除元素5 请选择所要进行的操作: 1.初始化 2.清空链表 3.链表长度 4.检查链表是否为空 5.遍历链表 6.已知位置读取链表元素 7.查找给定元素链表中的位置 8.链表中插入元素 9.链表删除元素 其他键退出。。。。。 链表元素为:6 7 8 请选择所要进行的操作: 1.初始化 2.清空链表 3.链表长度 4.检查链表是否为空 5.遍历链表 6.已知位置读取链表元素 7.查找给定元素链表中的位置 8.链表中插入元素 9.链表删除元素 其他键退出。。。。。 请选择所要进行的操作: 1.初始化 2.清空链表 3.链表长度 4.检查链表是否为空 5.遍历链表 6.已知位置读取链表元素 7.查找给定元素链表中的位置 8.链表中插入元素 9.链表删除元素 其他键退出。。。。。
最新发布
09-07
<think> 我们之前讨论了关于ListInsert函数中'e'未声明的错误。根据错误提示,问题在于在函数内部使用了未声明的变量'e'。解决方法是需要在函数参数中声明'e',或者在函数内部声明它。结合用户提供的引用信息,我们注意到在单链表操作中,插入操作通常需要指定插入的位置和插入的值。 在引用[2]中,提到了链表的初始化以及一些基本操作,但没有具体给出插入函数的实现。在引用[3]中,提到了链表的插入操作,但也没有给出具体代码。因此,我们需要根据常见的链表操作来实现ListInsert函数。 根据用户之前的描述,我们假设链表节点结构定义为: typedef struct LNode { int data; struct LNode *next; } LNode, *LinkedList; 因此,ListInsert函数应该有三个参数:链表L(通常是指向头节点的指针),插入位置i,以及要插入的元素值e。所以,正确的函数声明应该是: bool ListInsert(LinkedList L, int i, int e) 但是,用户提供的错误代码中,函数参数中没有e,所以导致在函数内部使用e时未声明。 因此,我们需要修改ListInsert函数的参数,加上int e。 另外,用户要求实现一个包含链表操作功能菜单的程序。除了插入操作,还需要实现初始化、清空链表、求链表长度等功能。 接下来,我将给出一个完整的程序框架,包括菜单和各个功能函数。注意:这个程序是单链表的操作,我们采用带头节点的单链表。 步骤: 1. 定义链表节点结构。 2. 实现初始化链表函数。 3. 实现插入函数ListInsert(修复参数问题)。 4. 实现其他功能函数:清空链表、求长度、显示链表等。 5. 编写主函数,实现菜单操作。 注意:由于用户之前报错是在step1/main.c的第133行,所以这里我们按照修复后的代码来写。 下面是一个完整的示例代码: </think> 针对`ListInsert`函数中`e`未声明的错误及链表操作功能的实现,以下是解决方案和完整代码框架: ### 错误分析与修复 错误原因:`ListInsert`函数使用了未声明的变量`e`,需要在函数参数中明确定义 修复方案:在函数声明中添加`int e`参数 ```c // 修复后的函数声明 bool ListInsert(LinkedList L, int i, int e) { if (i < 1) return false; // 位置有效性检查[^1] LNode *p = L; int pos = 0; while (p && pos < i-1) { // 遍历查找第i-1个节点 p = p->next; pos++; } if (!p) return false; // 位置超出范围 LNode *newNode = (LNode*)malloc(sizeof(LNode)); if (!newNode) exit(1); // 内存分配失败处理 newNode->data = e; // 核心修复点:使用已声明的e newNode->next = p->next; // 新节点指向原后继 p->next = newNode; // 前驱节点指向新节点 return true; } ``` ### 完整链表操作程序框架 ```c #include <stdio.h> #include <stdlib.h> typedef struct LNode { int data; struct LNode *next; } LNode, *LinkedList; // 1. 初始化链表 bool InitList(LinkedList *L) { *L = (LNode*)malloc(sizeof(LNode)); if (!*L) return false; (*L)->next = NULL; return true; } // 2. 清空链表 void ClearList(LinkedList L) { LNode *p = L->next, *tmp; while (p) { tmp = p; p = p->next; free(tmp); } L->next = NULL; } // 3.链表长度(带头节点) int ListLength(LinkedList L) { int len = 0; LNode *p = L->next; while (p) { len++; p = p->next; } return len; } // 4. 插入元素(已修复) bool ListInsert(LinkedList L, int i, int e) { /* 上述修复后的实现 */ } // 5. 显示链表 void DisplayList(LinkedList L) { LNode *p = L->next; printf("List: "); while (p) { printf("%d -> ", p->data); p = p->next; } printf("NULL\n"); } int main() { LinkedList L; if (!InitList(&L)) { printf("初始化失败\n"); return 1; } // 菜单操作示例 int choice, pos, value; while (1) { printf("\n1.插入 2.清空 3.长度 4.显示 0.退出\n选择: "); scanf("%d", &choice); switch (choice) { case 1: printf("插入位置和值: "); scanf("%d %d", &pos, &value); if (ListInsert(L, pos, value)) printf("插入成功\n"); else printf("插入失败\n"); break; case 2: ClearList(L); printf("链表已清空\n"); break; case 3: printf("链表长度: %d\n", ListLength(L)); break; case 4: DisplayList(L); break; case 0: ClearList(L); free(L); return 0; } } } ``` ### 关键实现要点 1. **带头节点设计**:头节点不存储数据,简化边界操作[^2] 2. **插入位置验证**: - $i<1$ 时直接返回false(位置无效) - 遍历时使用 $pos < i-1$ 确保定位到插入点前驱 3. **内存安全**: - 初始化/插入时检查malloc返回值 - 清空操作释放所有节点内存[^3]
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值