遍历二叉树的三种方法的六种实现
有详细(相对)的注释
(1)先序
力扣144.二叉树的前序遍历
https://leetcode-cn.com/problems/binary-tree-preorder-traversal/
递归:
class Solution
{
public:
void dfs(TreeNode *root, vector<int> &vec)
{
if (root != nullptr)
{
vec.push_back(root->val);
dfs(root->left, vec);
dfs(root->right, vec);
return;
}
else
return;
}
vector<int> preorderTraversal(TreeNode *root)
{
vector<int> re;
dfs(root, re);
return re;
}
};
栈:
怎么用栈实现呢。
先序遍历的过程是,访问中间的节点,再访问他的左子树和右子树。左子树也是先根节点,再左左子树。
所以,先访问根节点,然后访问左子树,根节点进栈,出栈的时候取出他的右子树这样?
比如根节点出栈,就访问右节点(右子树的根节点),它进栈,访问左子树
class Solution {
public:
vector<int> preorderTraversal(TreeNode *root) {
stack<TreeNode *> stk;
vector<int> re;
TreeNode *now = nullptr;
if (root != nullptr) {
re.push_back(root->val);
stk.push(root);
now = root->left;
}
while (!stk.empty()) {
if (now != nullptr) {
re.push_back(now->val);
stk.push(now);
now = now->left;
} else {
//now是空指针,上一个出栈,访问右
TreeNode *middle = stk.top(); //就是他左节点是空的
stk.pop();
TreeNode *right_node = middle->right;
if (right_node != nullptr) {
re.push_back(right_node->val);
stk.push(right_node);
//现在 right_node是这颗右子树的middle
now = right_node->left;
} else continue; //右节点也是空的
}
}
return re;
}
};
(2)中序
递归:
class Solution {
public:
void dfs(TreeNode* root, vector<int>& re ){
if(root== nullptr) return;
dfs(root->left, re) ;
re.push_back(root->val);
dfs(root->right, re);
}
vector<int> inorderTraversal(TreeNode* root) {
vector<int> re;
dfs(root, re);
return re;
}
};
循环:
就是把所有左节点都进栈。直到空指针就访问上一个左节点。
vector<int> inorderTraversal(TreeNode* root) {
vector<int> re;
stack<TreeNode*>stk;
auto now = root;
while(stk.empty()==0 || now!= nullptr){
if(now!= nullptr){ //这里可以用一个while遍历入栈左边一条链
stk.push(now);
now = now->left;
} else {
re.push_back(stk.top()->val);
now = stk.top()->right;
stk.pop();
}
}
return re;
}
(3)后序
递归:懒得写了
循环:遇到的问题是,出栈中间节点的时候,不知道右边有没有遍历过。【利用pre记录上一个访问过的结点 左节点】
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
vector<int>re;
stack<TreeNode*>stk;
auto now = root;
TreeNode* pre = nullptr;
while(!stk.empty() || now!= nullptr ){
while(now!= nullptr){
stk.push(now);
now = now->left;
}
auto middle = stk.top();
stk.pop();
if(middle->right== nullptr||pre==middle->right){
re.push_back(middle->val);
pre = middle;
}else{
now = middle->right;
stk.push(middle); //这里没想到
}
}
return re;
}
};
(4)一种不同的迭代 层次遍历
之前都是用的栈,这种用队列。
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
queue<TreeNode*>nodes;
vector <vector<int>>re;
if(!root) return re;
nodes.push(root);
while( !nodes.empty()){
auto size = nodes.size();
vector<int> line;
for(int i =1; i<=size; i++){ //这里没想到
auto now = nodes.front(); nodes.pop();
line.push_back(now->val);
if(now->left) nodes.push(now->left);
if(now->right) nodes.push(now->right);
}
re.push_back(line);
}
return re;
}
};
//ret.push_back(vector <int> ());
// ret.back().push_back(node->val);
学到一个C++vector这样插入一行的办法