合抱之木,生于毫末;九层之台,起于累土;千里之行,始于足下。💪🏻
一、题目描述 ⭐️
习题11-8 单链表结点删除
本题要求实现两个函数,分别将读入的数据存储为单链表、将链表中所有存储了某给定值的结点删除。链表结点定义如下: 👇🏻
struct ListNode {
int data;
ListNode *next;
};
函数接口定义: 👇🏻
struct ListNode *readlist();
struct ListNode *deletem( struct ListNode *L, int m );
函数readlist从标准输入读入一系列正整数,按照读入顺序建立单链表。当读到−1时表示输入结束,函数应返回指向单链表头结点的指针。
函数deletem将单链表L中所有存储了m的结点删除。返回指向结果链表头结点的指针。
裁判测试程序样例: 👇🏻
#include <stdio.h>
#include <stdlib.h>
struct ListNode {
int data;
struct ListNode *next;
};
struct ListNode *readlist();
struct ListNode *deletem( struct ListNode *L, int m );
void printlist( struct ListNode *L )
{
struct ListNode *p = L;
while (p) {
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
int main()
{
int m;
struct ListNode *L = readlist();
scanf("%d", &m);
L = deletem(L, m);
printlist(L);
return 0;
}
/* 你的代码将被嵌在这里 */
输入样例: ❀
10 11 10 12 10 -1
10
输出样例: ❀
11 12
二、代码(C语言)⭐️
// 创建一个新节点
struct ListNode* createNode(int data) {
// 为节点分配内存(注意:这里malloc参数应为sizeof(struct ListNode)而非sizeof(struct ListNode*))
struct ListNode *newNode = (struct ListNode *)malloc(sizeof(struct ListNode));
newNode -> data = data; // 设置节点数据
newNode -> next = NULL; // 初始化next指针为NULL
return newNode; // 返回新建的节点
}
// 从标准输入读入一系列正整数,按照读入顺序建立单链表
struct ListNode *readlist() {
int numArr[1000]; // 临时数组存储输入数字
int cnt = 0; // 计数器记录输入数字个数
// 循环读取输入直到-1
do {
scanf("%d",&numArr[cnt]);
if(numArr[cnt] == -1) break; // 遇到-1停止读取
cnt++;
} while(1);
if(cnt == 0) return NULL; // 如果没有输入任何数字(除了-1),返回空链表
// 创建链表头节点(假设至少有一个有效数字,否则这里需要判空)
struct ListNode *L = createNode(numArr[0]);
struct ListNode *p = L; // p指向当前链表末尾
// 为剩余数字创建节点并链接
for(int i = 1; i < cnt; i++) {
p -> next = createNode(numArr[i]); // 创建新节点并链接
p = p -> next; // 移动指针到新节点
}
return L; // 返回链表头指针
}
// 删除链表中所有值为m的节点
struct ListNode *deletem(struct ListNode *L, int m) {
struct ListNode *current = L; // 当前遍历节点
struct ListNode *prev = NULL; // 前驱节点
struct ListNode *temp; // 临时节点指针(用于释放内存)
// 处理头节点可能需要连续删除的情况(如多个连续m值开头)
while(current != NULL && current -> data == m) {
temp = current; // 保存要删除的节点
current = current -> next; // 移动current到下一个节点
free(temp); // 释放原头节点
}
L = current; // 更新链表头指针
// 遍历剩余链表节点
while(current != NULL) {
if(current -> data == m) { // 找到需要删除的节点
if(prev != NULL) {
prev -> next = current -> next; // 前驱节点跳过当前节点
}
temp = current; // 保存要删除的节点
current = current -> next; // 移动current
free(temp); // 释放节点内存
} else { // 不需要删除的节点
prev = current; // 更新前驱节点
current = current -> next; // 正常移动current
}
}
return L; // 返回删除后的链表头指针
}