该题呢,我给大家介绍两种解决的办法
首先大家先来看一下题目:
第一种方法:由于题目题目给的是head头指针,并没有给哨兵位指针。所以我们可以选择用三指针的方法来完成
首先第一种方法又分为两种情况:第一个的Val就是要删除的数据,以及第一个val不是要删除的数据。我们先来看下第一个不是val的情况
首先:我们定义一个指针cur来保存head指针,因为题目要求返回新的头节点,所以如果不对head保存而用head指针来进行遍历的话,那么我们就找不到头节点在哪个位置了。用next保存下一个节点的地址,方便找到val所在的节点的时候直接让val所在节点的前一个节点链接到next位置就可以。
其次:第一个数就为val也不需要太担心,我们只需要在上述第二种情况的代码里面加上一个if条件即可,第一个val就是要删除的数相当于链表所学过的头删。
struct ListNode* removeElements(struct ListNode* head, int val){
struct ListNode* cur = head; //保存一份head,用它来进行迭代(遍历)
struct ListNode* prev = NULL; //记录不是Val的位置
while(cur != NULL ) //不为空表
{
if(cur->val == val)
{
struct ListNode* next = cur->next;//保存当前节点的下一个节点,val等于val才用跳过当前节点cur
if(prev == NULL)//第一种情况:第一个数据就为要删除的val 相当于头删
{
free(cur);//直接释放掉空间,让head挪动到下一个节点的位置,再让cur挪动到head的位置
head = next;//让next位置成为头
cur = head;//保存头的位置,由cur进行迭代
}
else //第二种情况:第一个val不是要删除的数 这时候相当于第二种情况
{
free(cur);
cur = next;
prev->next = cur;
}
}
else //没找到val 就让cur迭代走起来查找哪个节点的val为要删除的那个元素 prev走过的路径是把val已经删除的路径
{
prev = cur;//没找到把prec挪动到cur位置
cur = cur->next;//cur指向下一个节点
}
}
return head; //返回头指针主函数打印链表
}
温馨提示:通过上述代码走读,结合图上的三指针一步一步进行画图挪动,来感受这三个指针到底是怎么移动的。单看代码的话很难理解
第二种方法:强行创建一个哨兵位(哨兵位并不拿来存放数据,但是哨兵位不等于NULL),用哨兵位等于上面的prev。
代码的具体实现其实跟第一种放大差别不大,我们就直接看代码了
struct ListNode* removeElements(struct ListNode* head, int val){
struct ListNode* Bheard = (struct ListNode*)malloc(sizeof(struct ListNode)); //动态开辟一个哨兵位
Bheard->next = head;//把哨兵位链接到链表中
struct ListNode* cur = head;//保存一份head,用它来进行迭代(遍历)
struct ListNode* prev = Bheard; //把不是val的节点链接起来
while(cur != NULL ) //不为空表
{
if(cur->val == val)
{
struct ListNode* next = cur->next;//保存当前节点的下一个节点,val等于val才用跳过当前节点
prev->next = next;//绕过cur节点为val的位置,直接链接到下一个
head = next;//
free(cur);
cur = next;
}
else
{
prev = cur;
cur = cur->next;
}
}
head = Bheard->next; //让head回到头部
free(Bheard);//因为是动态开辟出来的所以要释放
return head;
}