std::stack迭代遍历二叉树时访问弹出节点是否安全?
LeetCode二叉树中序遍历栈操作访问安全性解答
核心结论
你贴的这段中序遍历代码里,弹出栈元素后访问节点的操作完全安全,没有任何内存违规风险。
问题逐一解答
1. 弹出节点访问是否安全?pop()会不会释放new出来的节点内存?
- 先搞清楚栈里存的是什么:你定义的栈是
stack<TreeNode*> stk,栈里存的是指向TreeNode节点的指针,不是TreeNode实体对象本身。 std::stack的pop()只会销毁栈自己管理的内部元素,这里被销毁的是栈里存的那个指针变量,根本碰不到指针指向的、你用new分配在堆上的TreeNode内存——说白了就像你扔了写着家庭住址的便签纸,不可能把便签上写的那栋房子拆了。- 看你的代码顺序:先执行
root = stk.top(),把栈顶存的节点地址拷贝到外部的root变量里,之后才调用stk.pop()删掉栈里存的那个指针副本。这时候root变量里还好好存着节点的有效地址,访问root->val完全合法,根本不存在悬空指针的问题。 - 补一句常识:
pop()成员方法永远不会主动释放你通过new手动申请的堆内存,这部分内存只有你主动调用delete,或者持有它的智能指针生命周期结束时才会被回收。
2. 代码正常运行是不是因为容器弹出元素时不会立即释放存储空间?
- 这个猜测从根上就错了:当前场景下
pop()根本不会动你new出来的节点内存,代码能正常跑和「容器是不是延迟释放内存」半毛钱关系都没有。 - 就算退一步,你把栈定义成存值类型的
stack<TreeNode>(不是指针),pop()调用底层容器的pop_back()时,也会立刻调用元素的析构函数、回收容器给这个元素分配的存储空间,根本不存在「弹出元素不立即释放内存」的机制,你这个认知是有偏差的。
对应实现代码
class Solution { public: vector<int> inorderTraversal(TreeNode* root) { vector<int> res; stack<TreeNode*> stk; while (root != nullptr || !stk.empty()) { while (root != nullptr) { stk.push(root); root = root->left; } root = stk.top(); stk.pop(); res.push_back(root->val); root = root->right; } return res; } };
内容的提问来源于stack exchange,提问作者amont
相关产品推荐
相关产品推荐

