力扣203题:移除链表元素及代码实现分析
在链表操作中,删除指定元素是一个常见的任务。本文将详细解析两段C语言代码,它们都实现了从单链表中删除指定值的节点的功能。理解这两种方法,对于掌握链表操作和算法设计很有帮助。
单链表的结构定义
在开始分析代码之前,先看一下单链表节点的结构定义:
struct ListNode {
int val;
struct ListNode *next;
};
每个节点包含一个整数值 val 和一个指向下一个节点的指针 next 。
第一种实现方法
代码展示
struct ListNode* removeElements(struct ListNode* head, int val)
{
struct ListNode*newcode=NULL;
struct ListNode*temp=NULL;
struct ListNode*cur=head;
while(cur)
{
if(cur->val!=val)
{
if(temp==NULL)
{
newcode=temp=cur;
}
else
{
temp->next=cur;
temp=temp->next;
}
cur=cur->next;
}
else
{
struct ListNode*next=cur->next;
free(cur);
cur=next;
}
}
if(temp)
temp->next=NULL;
return newcode;
}
代码解析
初始化指针: newcode 用于指向新链表的头节点, temp 用于遍历新链表, cur 用于遍历原链表。
遍历原链表:使用 while 循环遍历链表, cur 依次指向每个节点。
判断节点值:如果当前节点的值不等于要删除的值 val ,则将其加入新链表。如果新链表为空,将 newcode 和 temp 都指向当前节点;否则,将当前节点接到 temp 的后面,并更新 temp 。
删除节点:如果当前节点的值等于 val ,保存下一个节点的指针,释放当前节点,然后将 cur 指向下一个节点。
处理链表末尾:遍历结束后,将新链表的最后一个节点的 next 设为 NULL ,防止出现野指针。
返回结果:返回新链表的头节点 newcode 。
第二种实现方法
代码展示
struct ListNode* removeElements(struct ListNode* head, int val)
{
struct ListNode*pre=NULL;
struct ListNode*tmp=head;
while(tmp)
{
if(tmp->val!=val)
{
pre=tmp;
tmp=tmp->next;
}
else
{
if(pre==NULL)
{
tmp=head->next;
free(head);
head=tmp;
}
else
{
pre->next=tmp->next;
free(tmp);
tmp=pre->next;
}
}
}
return head;
}
代码解析
初始化指针: pre 用于指向当前节点的前一个节点, tmp 用于遍历链表。
遍历链表:使用 while 循环遍历链表, tmp 依次指向每个节点。
判断节点值:如果当前节点的值不等于 val ,则将 pre 指向当前节点,然后 tmp 指向下一个节点。
删除节点:如果当前节点的值等于 val ,分两种情况处理。如果 pre 为空,说明当前节点是头节点,更新头节点并释放原头节点;否则,将 pre 的 next 指向 tmp 的下一个节点,释放 tmp ,然后将 tmp 指向 pre 的下一个节点。
返回结果:返回更新后的头节点 head 。
总结
这两种方法都能有效地从单链表中删除指定值的节点。第一种方法通过构建新链表来实现,逻辑较为清晰;第二种方法则直接在原链表上进行删除操作,更节省空间。在实际应用中,可以根据具体需求选择合适的方法。理解和掌握这些链表操作技巧,有助于提升编程能力和解决实际问题的能力。