本题要求实现两个函数,分别将读入的数据存储为单链表、将链表中所有存储了某给定值的结点删除。链表结点定义如下:
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;
}
/* 你的代码将被嵌在这里 */
看了一些题解,都没有设置头节点,直接在第一个节点存数据,这样反而在逻辑细节上不易理解。其实设置头节点逻辑更清晰,代码也简化了很多,比较容易理解。
struct ListNode* readlist() {
struct ListNode* head, * tail;
head = malloc(sizeof(struct ListNode));
tail = head;
while (1) {
struct ListNode* ptr = (struct ListNode*)malloc(sizeof(struct ListNode)); // 创建新节点
scanf("%d", &ptr->data); // 插入数据
if (ptr->data == -1) break;
tail->next = ptr; // 连接到新结点
tail = ptr; // 尾指针下移
}
tail->next = NULL; // 循环结束,给尾指针的next赋值为空
return head;
}
struct ListNode* deletem(struct ListNode* L, int m) {
struct ListNode* head, * ptr;
ptr = L, head = L;
while(ptr->next != NULL) { // 因为头节点不存数据,所以直接从头结点的next遍历
if (ptr->next->data == m) {
struct ListNode* del = (struct ListNode*)malloc(sizeof(struct ListNode)); // 创建指针
del = ptr->next; // 指向这个即将被释放的空间
ptr->next = ptr->next->next; // 跳过要删除的节点,指向被删节点的下一个节点
free(del); // 释放被删节点的内存空间
continue;
}
ptr = ptr->next;
}
return head->next; // 这里注意返回的是第二个节点,因为头节点是不存数据的,第二个节点保存的就是的第一份数据
}