链表删除位置可被5整除的节点时无法删除末尾节点问题求解
问题背景
尝试删除链表中所有位置序号可被5整除的节点时,现有实现无法删除符合条件的末尾节点,原有代码如下:
void removeDivFive(Node* head){ int count = 0; Node* temp = head; while(temp != NULL){ count++; if(count%5==0){ if(temp->next != NULL){ temp->value = temp->next->value; temp->next = temp->next->next; } } temp = temp->next; } while(head != NULL){ cout<<head->value; head = head->next; } }
原有实现逻辑为:遍历到符合删除条件的节点时,将下一个节点的值复制到当前节点,再将当前节点的next指针修改为指向后继节点的next节点。当链表总长度为10时,最后一个符合条件的节点无法被正常删除。
问题根因
- 现有删除逻辑的成立前提是待删除节点必须存在非空后继节点:逻辑本质是删掉待删除节点的下一个节点,用下一个节点的值顶替当前待删除节点,根本不是真的删除当前遍历到的节点。
- 当待删除节点是链表尾节点(比如总长10时的第10个节点),它的
next指针为NULL,代码中if(temp->next != NULL)的判断会直接跳过删除流程,尾节点就被保留了下来。就算移除这个判断,逻辑也无法执行——尾节点没有后继节点,既找不到值用来覆盖当前节点,也没有后继的next指针可以挂载。 - 原有代码没有释放被删除节点的内存,会触发内存泄漏问题。
修复方案
采用标准链表删除的双指针逻辑,跟踪当前遍历节点的前驱节点,找到待删除节点时直接让前驱节点跨过待删除节点指向后继,不需要复制节点值,可覆盖所有位置(包括尾节点)的删除场景,修复后代码如下:
void removeDivFive(Node* head){ int count = 0; Node* curr = head; Node* prev = NULL; // 记录当前节点的前驱节点 while(curr != NULL){ count++; if(count % 5 == 0){ Node* toDelete = curr; if(prev != NULL){ prev->next = curr->next; }else{ // 兼容待删除节点为头节点的极端场景 head = curr->next; } curr = curr->next; delete toDelete; // 释放被删除节点内存,避免泄漏 }else{ prev = curr; curr = curr->next; } } // 打印结果验证 Node* printTemp = head; while(printTemp != NULL){ cout << printTemp->value; printTemp = printTemp->next; } }
如果要保留原有复制后继节点的删除思路,需要先遍历一次计算链表总长度,对最后一个符合整除5条件的尾节点做特殊处理:遍历到尾节点的前驱时直接释放尾节点、把前驱的next设为NULL即可,但这种方案需要两次遍历链表,效率低于双指针方案。
内容的提问来源于stack exchange,提问作者EL02
相关产品推荐
相关产品推荐

