赞
踩
文档讲解:代码随想录
视频讲解: 关于二叉树,你该了解这些!| 二叉树理论基础一网打尽,二叉树的种类、二叉树的存储方式、二叉树节点定义、二叉树的遍历顺序
>状态
//回顾链表的定义 struct ListNode* { int val; ListNode* next; ListNode(int x):val(x),next(nullptr){} }; //二叉树链式存储 struct TreeNode { int val; TreeNode* left; TreeNode* right; TreeNode(int x):val(x),left(nullptr),right(nullptr){} };
文档讲解:代码随想录
视频讲解: 每次写递归都要靠直觉? 这次带你学透二叉树的递归遍历
状态
void returnTree(TreeNode* cur,vector<int>& list)
{
//先判断,防止访问指针出错
if(cur== nullptr) return ;
//按顺序递归 中左右
list.push_back(cur->val);
returnTree(cur->left,list);
returnTree(cur->right,list);
}
void returnTree(TreeNode* cur,vector<int>& list)
{
//先判断,防止访问指针出错
if(cur== nullptr) return ;
//按顺序递归 左右
returnTree(cur->left,list);
lust.push_back(cur->val);
returnTree(cur->right,list);
}
void returnTree(TreeNode* cur,vector<int>& list)
{
//先判断,防止访问指针出错
if(cur== nullptr) return ;
//按顺序递归 左右
returnTree(cur->left,list);
returnTree(cur->right,list);
lust.push_back(cur->val);
}
文档讲解:代码随想录
视频讲解:
状态
利用栈来实现遍历。整个迭代分为两个步骤
处理:将元素放进数组中
访问:遍历节点
首先压入头节点,然后取出头节点的时候压入右节点和左节点(先入后出满足中左右),之后每当取出一个节点都要将其的右子节点和左子节点压入,直到取出节点的左子节点为空。
需要先判断当前树是否为空,如果为空直接返回
class Solution { public: vector<int> preorderTraversal(TreeNode* root) { vector<int> res; stack<TreeNode*> treestack; if(root!=nullptr) treestack.push(root); while(!treestack.empty()) { //暂存,方便取左子和右子 TreeNode* temp = treestack.top(); //存放 res.push_back(temp->val); //弹出 treestack.pop(); //将右子节点压入 if(temp->right) treestack.push(temp->right); //左子节点压入 if(temp->left) treestack.push(temp->left); } return res; } };
左中右,我们就不能像前序那样了,因为前序的处理和访问都是中节点,所以只需要一个中节点指针控制,而中序我们访问的是中节点,但实际处理的是左子节点。所以可以增加一个指针来控制返回结果的存储。
class Solution { public: vector<int> inorderTraversal(TreeNode* root) { vector<int> res; stack<TreeNode*> treestack; TreeNode* temp = root; while(temp!=nullptr || !treestack.empty()) { //头节点开始所有左节点的压入 if(temp!=nullptr) { treestack.push(temp); temp = temp->left; } //此时temp为最左节点 else { temp = treestack.top(); treestack.pop(); res.push_back(temp->val); //将处理指针指向最左端节点的右子树 temp = temp->right; //如果不为空,则将访问第二个最左边的节点 //如果为空,则将访问最左节点的中节点,其也为最左边节点 } } return res; } };
虽然我们处理的和访问的仍然不是一个指针,甚至变得更多,但发现如果将前序迭代的结果变成中右左,然后将结果翻转是不是就是左右中了呢。所以我们只需要修改前序迭代的遍历就可以了。
class Solution { public: vector<int> postorderTraversal(TreeNode* root) { vector<int> res; stack<TreeNode*> treestack; if(root!=nullptr) treestack.push(root); while(!treestack.empty()) { TreeNode* temp = treestack.top(); res.push_back(temp->val); treestack.pop(); if(temp->left) treestack.push(temp->left); if(temp->right) treestack.push(temp->right); } int left = 0; int right = res.size()-1; while(left<right) { swap(res[left++],res[right--]); } return res; } };
具体参考
同样考虑处理和访问的节点,我们对要访问的节点在访问入栈之后加上标记,如果出现这个标记则开始进行处理。
栈在开始处理之前的最后一步访问,此时栈里面右整个树的所有节点。
而我们访问的永远都是中节点,并且记住栈是先进后出,所以对于中序遍历左中右,入栈方式应该是右中左,然后在中节点后加上null,右中null左。
对于前序,入站方式就是右左中Null,后序就是中null右左。
当我们遇到null就开始处理元素存入数组的操作
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。