题目要求
本题要求实现两个函数,分别将读入的数据存储为单链表、将链表中所有存储了某给定值的结点删除。链表结点定义如下:
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
解题思路
结合所给代码,可分析代码实现过程如下:
通过 readlist() 函数将输入的数据存储到链表中,再调用 deletem() 函数来删除链表中指定的元素,最后通过 printlist() 函数输出最终的链表结果。
其中,struct ListNode 为链表节点结构体,包含两个成员变量:int data 表示当前节点存储的数据,struct ListNode *next 表示指向下一个节点的指针。
-
函数 void printlist(struct ListNode *L) 用于遍历整个链表并打印出每个节点的值;
-
函数 struct ListNode *readlist() 用于读取输入的数据并生成链表;
-
函数 struct ListNode *deletem(struct ListNode *L, int m) 用于删除链表中所有值为 m 的节点,并返回处理后的链表。
代码
struct ListNode *readlist() // 读取链表
{
struct ListNode *head,*p1,*p2; // 定义头结点和两个临时指针变量
int n=0; // 定义节点数量
head = NULL; // 初始化头结点为空指针
p1 = p2 = (struct ListNode*)malloc(sizeof(struct ListNode)); // 开辟新空间
scanf("%d",&p1->data); // 从键盘上读入第一个节点的数据
while(p1->data!=-1) // 如果当前节点不是最后一个节点
{
n++; // 记录节点个数
if(n==1) // 如果是头节点
head = p1; // 将当前节点作为头结点
else
p2->next = p1; // 将前一个节点指针指向当前节点
p2 = p1; // 将 p1 赋值给 p2,以便在下一次循环中使用
p1 = (struct ListNode*)malloc(sizeof(struct ListNode)); // 为下一节点开辟新空间
scanf("%d",&p1->data); // 读入下一个节点的数据
}
p2->next = NULL; // 最后一个节点指向 NULL
return head; // 返回头结点指针
}
struct ListNode *deletem( struct ListNode *L, int m ) // 删除指定元素
{
struct ListNode *p1,*p2; // 定义两个指针变量
p1 = L; // 将 L(链表的头结点)赋值给 p1
while(p1!=NULL) // 循环遍历链表
{
if(p1->data==m) // 如果当前节点存储的数据等于待删除的数 m
{
if(p1==L) // 如果当前节点是头节点
L = p1->next; // 将头指针指向当前节点的下一个节点,即删除头节点
else
p2->next = p1->next; // 将前一个节点的指针指向当前节点的下一个节点,即删除中间节点或尾节点
}
else
{
p2 = p1; // 将 p1 赋值给 p2,以便在下一次循环中使用
}
p1 = p1->next; // 将 p1 指向下一个节点
}
return L; // 返回操作后的链表
}
完整代码如下:
#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;
}
struct ListNode *readlist() // 读取链表
{
struct ListNode *head,*p1,*p2; // 定义头结点和两个临时指针变量
int n=0; // 定义节点数量
head = NULL; // 初始化头结点为空指针
p1 = p2 = (struct ListNode*)malloc(sizeof(struct ListNode)); // 开辟新空间
scanf("%d",&p1->data); // 从键盘上读入第一个节点的数据
while(p1->data!=-1) // 如果当前节点不是最后一个节点
{
n++; // 记录节点个数
if(n==1) // 如果是头节点
head = p1; // 将当前节点作为头结点
else
p2->next = p1; // 将前一个节点指针指向当前节点
p2 = p1; // 将 p1 赋值给 p2,以便在下一次循环中使用
p1 = (struct ListNode*)malloc(sizeof(struct ListNode)); // 为下一节点开辟新空间
scanf("%d",&p1->data); // 读入下一个节点的数据
}
p2->next = NULL; // 最后一个节点指向 NULL
return head; // 返回头结点指针
}
struct ListNode *deletem( struct ListNode *L, int m ) // 删除指定元素
{
struct ListNode *p1,*p2; // 定义两个指针变量
p1 = L; // 将 L(链表的头结点)赋值给 p1
while(p1!=NULL) // 循环遍历链表
{
if(p1->data==m) // 如果当前节点存储的数据等于待删除的数 m
{
if(p1==L) // 如果当前节点是头节点
L = p1->next; // 将头指针指向当前节点的下一个节点,即删除头节点
else
p2->next = p1->next; // 将前一个节点的指针指向当前节点的下一个节点,即删除中间节点或尾节点
}
else
{
p2 = p1; // 将 p1 赋值给 p2,以便在下一次循环中使用
}
p1 = p1->next; // 将 p1 指向下一个节点
}
return L; // 返回操作后的链表
}
总结
该题考察了链表的基本操作,包括链表的创建、遍历、删除指定元素等。
此外,还涉及到如何使用动态内存分配函数 malloc
和函数指针等知识点。
我是秋说,我们下次见。
标签:p2,结点,p1,ListNode,struct,PTA,C语言,链表,节点 From: https://www.cnblogs.com/qiushuo/p/17481443.html