一、删除功能需要实现的目标
我希望实现一个能够在链表任意位置删除一个节点的函数 Delete(),传入目标链表的head节点,以及删除的位置。
假设链表当前的长度为n,关于删除的位置 pos,当 pos 小于1或大于 n 时,认为这是一个不合法的插入位置。
二、在链表的任意位置删除一个节点
1、Delete()实现的逻辑
要删除第 pos 个节点,我们首先需要找到第 pos-1 个节点,然后将第 pos-1 个节点指向第pos+1 个节点。随后需要释放第 pos 个节点的内存,否则将引起内存泄漏。
Delete()函数需要两个参数,一个是链表头节点的地址,另一个是要删除的节点位置。
(1)首先判断 pos<1 时,删除的节点位置非法,不进行任何操作,直接返回原先的头节点地址。
(2)处理删除的就是头节点时的情况。在这里默认传入的链表至少有一个节点。
(3)定义一个变量追踪位置,然后使用 while 循环遍历到指定位置的前一个节点。
(4)定义一个temp2用于保存将要删除的节点,也即第 pos 个节点。随后进行处理,当能到达指定位置时,建立新的连接,将第 pos-1 个节点指向第 pos+1 个节点。
这里注意一个特殊情况,若链表长度为n,当 pos = n+1,此时while循环仍然会遍历到最后一个节点,temp2 = NULL,temp2->next也就没有意义,所以我在这里增加了一个判断,只有temp2不为NULL才进行删除操作。free操作接收NULL时没有意义,所以不用修改。
最后无法到达指定位置时,也不进行任何操作。
struct Node* Delete(struct Node* head, int pos) {
if(pos < 1) return head;
struct Node* temp1 = head; //要删除的就是头节点
if (pos == 1) {
head = head->next;
free(temp1);
return head;
}
int currentPos = 1; // 用来追踪当前的位置
while (temp1->next != NULL && currentPos < pos - 1) { // 遍历到指定位置的前一个节点
temp1 = temp1->next;
currentPos++;
}
struct Node* temp2 = temp1->next; //temp2保存将要删除的的节点
if (currentPos == pos - 1) { // 如果能到达指定位置
if (temp2 != NULL)
temp1->next = temp2->next;
else
temp1->next = NULL;
free(temp2);
}
else {
// 不能到达指定位置,不进行删除操作
return head;
}
return head;
}
2、完整代码
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node* next;
};
struct Node* Insert(struct Node* head, int val, int pos) {
if (pos < 1) return head;
struct Node* temp1 = (struct Node*)malloc(sizeof(struct Node));
temp1->data = val;
temp1->next = head;
if (pos == 1) {
temp1->next = head;
head = temp1;
return head;
}
struct Node* temp2 = head;
int currentPos = 1; // 用来追踪当前的位置
while (temp2->next != NULL && currentPos < pos - 1) { // 遍历到指定位置的前一个节点
temp2 = temp2->next;
currentPos++;
}
if (currentPos == pos - 1) { // 如果能到达指定位置
temp1->next = temp2->next; // 新节点的next指向原位置节点的next
temp2->next = temp1; // 将新节点插入到链表中
}
else {
// 这里我们选择在链表末尾添加
temp2->next = temp1;
temp1->next = NULL;
}
return head;
}
void PrintList(struct Node* head) {
printf("List is: ");
while (head != NULL)
{
printf(" %d", head->data);
head = head->next;
}
printf("\n");
}
struct Node* Delete(struct Node* head, int pos) {
if(pos < 1) return head;
struct Node* temp1 = head;
if (pos == 1) {
head = head->next;
free(temp1);
return head;
}
int currentPos = 1; // 用来追踪当前的位置
while (temp1->next != NULL && currentPos < pos - 1) { // 遍历到指定位置的前一个节点
temp1 = temp1->next;
currentPos++;
}
struct Node* temp2 = temp1->next; //temp2保存将要删除的的节点
if (currentPos == pos - 1) { // 如果能到达指定位置
if (temp2 != NULL)
temp1->next = temp2->next;
else
temp1->next = NULL;
free(temp2);
}
else {
// 不能到达指定位置,不进行删除操作
return head;
}
return head;
}
int main()
{
struct Node* head = NULL; //empty list
head = Insert(head, 2, 1); //List:2
head = Insert(head, 3, 2); //List:2 3
head = Insert(head, 4, 2); //List:2 4 3
head = Insert(head, 5, 2); //List:2 5 4 3
PrintList(head);
head = Delete(head, 6); //List:2 5 4 3
head = Delete(head, 7); //List:2 5 4 3
PrintList(head);
head = Delete(head, 4); //List:2 5 4
PrintList(head);
head = Delete(head, 1); //List:5 4
PrintList(head);
return 0;
}
运行结果: