删除二叉树指定节点及其所有子节点时目标父节点未被删除的代码问题
代码问题拆解
你的实现之所以出现“子节点删除成功、目标父节点残留”的现象,是三个错误叠加导致的:
1. 全流程没有执行任何有效的内存释放,所有free调用都是空操作
C语言中free必须传入指向待释放内存的有效地址才能完成回收,但你代码里所有free的传参全是NULL:
deleteVaccinated函数内部,你先把局部指针变量root赋值为NULL,再调用free(root),等价于执行free(NULL),完全不会释放对应节点的内存- 回到主逻辑里,你把
deleteVaccinated的固定返回值NULL重新赋值给gotVaccinated,之后再调用free(gotVaccinated),依然是对NULL执行释放操作,没有任何实际效果 - 递归流程里你只是把待删节点内部的左/中/右孩子指针全部设为
NULL,看起来像是删掉了下层子节点,但待删目标节点本身的内存完全没有被回收,自然会残留。
2. 没有清空父节点指向待删目标节点的指针,造成结构上的“未删除”假象
当待删节点不是整棵树的根时:
- 你通过
findNode拿到了待删节点的父节点father,但找到目标后,完全没有修改father节点内部存储的左/中/右孩子指针 - 哪怕后续正确释放了待删节点的内存,父节点里存的旧地址依然会形成悬空指针,后续树遍历的时候依然能顺着这个指针访问到原本应该被删掉的节点,从结构视角看就像目标节点根本没被删除。
3. 逻辑冗余错位
你在主函数里额外写的free(gotVaccinated),本质是想补释放节点内存,但因为前面的赋值流程已经把gotVaccinated变量改成了NULL,这行操作完全没有作用,反而让释放逻辑更混乱。
修正方向
- 调整
deleteVaccinated内部的释放顺序:先递归释放完所有孩子的内存、打印节点信息,先调用free(root)释放当前节点内存,再把指针置为NULL返回,不要反过来写置空和释放的顺序 - 当待删节点不是根节点时,在完成整棵子树的内存释放后,必须在父节点上把指向待删节点的对应孩子指针(左/中/右)赋值为
NULL,完成树结构的正确裁剪 - 删掉主函数里多余的、无效的重复
free调用,统一把所有节点的释放逻辑收敛到递归删除函数里 - 修正打印文案,当前打印的“Survived(存活)”和“删除节点”的操作目的完全相反,可以根据实际需求调整为提示节点已被移除的内容。
内容的提问来源于stack exchange,提问作者Netanel
相关产品推荐
相关产品推荐

