链表的理论基础:
链表是通过指针串联起来的顺序存储结构,链表的每一个元素称为节点,每一个节点都有数据域和指针域(指向下一个节点),最后一个节点的指针域为NULL指针,链表第一个元素的指针称为头节点
关于更详细的请看这篇文章syseptember的个人博客:无头单向链表
203. 移除链表元素
思路
链表删除元素是通过变换指针指向
而实现的,如下链表 1 4 2 4举例
tips:使用C/C++删除链表节点时需要手动释放删除的节点内存
直接删除
删除一个节点时需要将该节点
的前一个结点的指针域
指向该节点的下一个节点
但是第一个节点不存在前一个结点,所以直接删除的话需要分两种情况讨论
- 删除的是头节点
- 删除的不是头节点
代码
//直接移除
struct ListNode* removeElements(struct ListNode* head, int val){
typedef struct ListNode ListNode;
ListNode* tmp;
//判断是否需要头删
while (head && head->val == val)
{
tmp = head;//记录删除位置
head = head->next;
free(tmp);//释放删除位置
}
//删除的元素不在头部
ListNode* cur = head;
//保证cur和cur->next不为空
while (cur && (tmp = cur->next))
{
if (cur -> next -> val == val)
{
cur->next = cur->next->next;//前节点的指针域指向后一个节点
free(tmp);//释放删除节点
}
else
{
cur = cur -> next;
}
}
return head;
}
虚拟头节点
在删除过程中,因为头节点没有前一个结点所以我们需要分类讨论,如果我们给头节点前面加上一个节点,那么此时头节点也可以后非头节点进行统一的处理的,新加上的节点为虚拟头节点
代码
//虚拟头节点
struct ListNode* removeElements(struct ListNode* head, int val){
typedef struct ListNode ListNode;
ListNode* dummyHead = (ListNode*)malloc(sizeof(ListNode));
dummyHead->next = head;
ListNode* cur = dummyHead;
ListNode* tmp;
//直到遍历到尾节点
while (cur->next)
{
if (cur->next->val == val)
{
tmp = cur->next;
cur->next = cur->next->next;
free(tmp);
}
else
{
cur = cur->next;
}
}
//不要返回head,如果头删的话head已经被释放了
return dummyHead->next;
}