中序递归遍历
注意点
1.一定要判断root==nullptr,要不然leetcode上会报
Line x: member access within null pointer of type ‘struct TreeNode’
原因:在测试过程中,第x行访问的指针为NULL,通常情况下表明程序未对NULL情况作出判断。
2.递归本身便是循环,所以不能加while(root)
3.leetcode上的原题是要将遍历结果写入到一个vector中,所以要写一个单独的函数来接收res
4.中序遍历就要写在两个 遍历中间
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
std::vector<int> result;
recordInorderTraversal(root,result);
return result;
}
void recordInorderTraversal(TreeNode* root, std::vector<int>& result) {
if(root==nullptr) {
return;
}
recordInorderTraversal(root->left,result);
result.push_back(root->val);
recordInorderTraversal(root->right,result);
}
};
非递归的中序
注意点:
1.stack的用法,模板类型一定要是TreeNode*;
2.注意出栈的时和访问的时机;
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
std::vector<int> result;
stack<TreeNode*> s;
if(!root) {
return result;
}
while(root) {
s.push(root);
root = root->left;
}
while(!s.empty()) {
TreeNode* tree_node = s.top();
result.push_back(tree_node->val);
s.pop();
TreeNode* right_tree_node = tree_node->right;
while(right_tree_node) {
s.push(right_tree_node);
right_tree_node = right_tree_node -> left;
}
}
return result;
}
};
前序递归遍历
可以看到前序就要是在最前面存储(打印)节点数据,中序就是在中间
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
std::vector<int> result;
onPreorderTraversal(root, result);
return result;
}
void onPreorderTraversal(TreeNode* root,std::vector<int>& result) {
if(root==nullptr)
return ;
result.push_back(root->val);
onPreorderTraversal(root->left,result);
onPreorderTraversal(root->right,result);
}
};
前序的非递归
注意点(总结):
在做完中序和前序之后,会发现都是一股脑将根结点以及它的左子树压送到栈中。出栈时再将右子树拿出来,按照同样的方式操作一次。
不同的点,在于中序是在出栈时访问,前序是在压栈时访问。
相同点,在于都是一样的代码逻辑:
1.起一个循环将根及其左子树,压入栈;
2.新起一个循环,判断栈不为空时,出栈顶元素;
3.如果该元素的右子树不为空,则再在2的循环里新起一个循环执行步骤1;
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
std::vector<int> result;
stack<TreeNode*> s;
if(root == nullptr) {
return result;
}
while(root) {
s.push(root);
result.push_back(root->val);
root = root->left;
}
while(!s.empty()) {
TreeNode* tempNode = s.top();
tempNode = tempNode->right;
s.pop();
while(tempNode) {
s.push(tempNode);
result.push_back(tempNode->val);
tempNode = tempNode->left;
}
}
return result;
}
};
后序递归
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
std::vector<int> result;
onPostorderTraversal(root,result);
return result;
}
void onPostorderTraversal(TreeNode* root, std::vector<int>& result) {
if(!root) {
return ;
}
onPostorderTraversal(root->left,result);
onPostorderTraversal(root->right,result);
result.push_back(root->val);
}
};
后序非递归
只有当前结点的右子树为空或被遍历过了,才能遍历该结点。
如何知道右子树被遍历完了呢??~。。。
栈是后进先出的,意味着之后续遍历相对复杂,原因就在于出栈的情况不一样了。
在先序和中序遍历过程中,只要左子树处理完毕实际上栈顶元素就可以出栈了,但是后续遍历情况不同,只有左子树和右子树都遍历完毕才可以处理当前节点。那么该如何知道当前节点的左子树和右子树都处理完了呢?
显然需要某种方法记录下遍历的过程,实际上只需要记录下遍历的前一个节点就足够了。
如果我们知道了遍历过程中的前一个节点,那么我们就可以做如下判断了:
如果前一个节点是当前节点的右子树,那么说明右子树遍历完毕可以pop了
如果前一个节点是当前节点的左子树而且当前节点右子树为空,那么说明可以pop了
如果当前节点的左子树和右子树都为空,也就是叶子节点那么说明可以pop了
原文链接:https://blog.csdn.net/github_37382319/article/details/99656769
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
std::vector<int> result;
stack<TreeNode*> s;
TreeNode* last = nullptr;
if(root == nullptr) {
return result;
}
while(root) {
s.push(root);
root = root->left;
}
while(!s.empty()) {
TreeNode* tempNode = s.top();
if(tempNode->right==nullptr||
tempNode->right==last){
s.pop();
result.push_back(tempNode->val);
last = tempNode;
} else {
tempNode = tempNode->right;
while(tempNode) {
s.push(tempNode);
tempNode = tempNode->left;
}
}
}
return result;
}
};
总做流程上来看还是一样的,只是出栈时做了一点的处理,后序要麻烦一些,需要一个辅助变量来实现,目前来看记住吧~