【算法笔记】二叉树遍历

1 先序遍历

1.1 递归

void preOrder(TreeNode* root, vector<int>& preRes) {
    //根左右
    if(root == nullptr) return;
    preRes.push_back(root->val);
    preOrder(root->left, preRes);
    preOrder(root->right, preRes);
}

1.2 迭代

void preOrder(TreeNode* root, vector<int>& preRes) {
    //根左右
    stack<TreeNode*> stk;
    stk.push(root);  //根节点入栈
    while(!stk.empty()) {
        TreeNode *tmp = stk.top();  //当栈非空时,栈顶出栈
        stk.pop();
        preRes.push_back(tmp->val);
        if(tmp->right) stk.push(tmp->right); //先进后出,右子节点先入栈
        if(tmp->left) stk.push(tmp->left); //左子节点后入栈先出栈
    }
}

1.3 引申

1.3.1 翻转二叉树

//递归
TreeNode* invertTree(TreeNode* root) {
    if(root == nullptr) return nullptr;
    swap(root->left, root->right);
    invertTree(root->left);
    invertTree(root->right);
    return root;
}

//辅助栈
TreeNode* invertTree(TreeNode* root) {
    stack<TreeNode*> stk;
    stk.push(root);
    while(!stk.empty()) {
        TreeNode *node = stk.top();
        stk.pop();
        if(root == nullptr) continue;
        swap(node->left, node->right);  //交换左右子节点
        stk.push(node->right);
        stk.push(node->left);
    }
    return root;
}

1.3.2 LC538 把二叉搜索树转换为累加树

题意:使每个节点node的新值等于原树中大于或等于node->val的值之和

int num = 0;
TreeNode* convertBST(TreeNode* root) {
    //利用二叉搜索树的性质,右根左 -> 从大到小
    if(root == nullptr) return nullptr;
    if(root->right) convertBST(root->right);
    num += root->val;
    root->val = num;
    if(root->left) convertBST(root->left);
    return root;
}

1.3.3 LC617 合并二叉树

TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
    if(root1 == nullptr) return root2;
    if(root2 == nullptr) return root1;
    root1->val += root2->val;
    root1->left = mergeTrees(root1->left, root2->left);
    root1->right = mergeTrees(root1->right, root2->right);
    return root1;
}

2 中序遍历

2.1 递归

void inOrder(TreeNode* root, vector<int>& inRes) {
    //左根右
    if(root == nullptr) return;
    inOrder(root->left, inRes);
    inRes.push_back(root->val);
    inOrder(root->right, inRes);
}

2.2 迭代

void inOrder(TreeNode* root, vector<int>& inRes) {
    //左根右
    stack<TreeNode*> stk;
    while(root != nullptr || !stk.empty()) { //当栈非空或root非nullptr时循环
        while(root != nullptr) {
            stk.push(root);   //遍历左子节点入栈
            root = root->left;
        }
        root = stk.top();
        stk.pop();
        inRes.push_back(root->val);
        root = root->right;
    }
}

3 后序遍历

3.1 递归

void postOrder(TreeNode* root, vector<int>& postRes) {
    //左右根
    if(root == nullptr) return;
    postOrder(root->left, postRes);
    postOrder(root->right, postRes);
    postRes.push_back(root->val);
}

3.2 迭代

void postOrder(TreeNode* root, vector<int>& postRes) {
    //左右根
    stack<TreeNode*> stk1;  //根右左
    stack<TreeNode*> stk2;  //stk1的倒序即为后序遍历
    stk1.push(root);
    while(!stk1.empty()) {
        root = stk1.top();
        stk1.pop();
        stk2.push(root);
        if(root->left) stk1.push(root->left);
        if(root->right) stk1.push(root->right);
    }
    while(!stk2.empty()) {
        postRes.push_back(stk2.top()->val);
        stk2.pop();
    }
}

3.3 引申

3.3.1 二叉树的最近公共祖先

最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)

TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
    //递归终止条件
    if(root == nullptr || root == p || root == q) return root;

    //自底向上遍历
    TreeNode *left = lowestCommonAncestor(root->left, p, q);
    TreeNode *right = lowestCommonAncestor(root->right, p, q);

    if(left != nullptr && right != nullptr) return root;
    return left ? left : right;
    return nullptr;
}

4 层序遍历

4.1 JZ32 -2 从上到下打印二叉树

class Solution {
public:
    vector<vector<int> > levelOrder(TreeNode* root) {
        // write code here
        vector<vector<int>> res;
        if(!root) return res;
        queue<TreeNode*> q;
        q.push(root);
        while(!q.empty()) {
            vector<int> level;  //局部变量
            int size = q.size();
            for(int i = 0; i < size; ++i) {  //遍历层
                TreeNode *node = q.front();
                q.pop();
                level.push_back(node->val);
                if(node->left) q.push(node->left);  //当前节点的左右子节点入队列
                if(node->right) q.push(node->right);
            }
            res.push_back(level);
        }
        return res;
    }
};

4.2 JZ32 -3 从上到下之字形打印二叉树

vector<vector<int>> levelOrder(TreeNode* root) {
    vector<vector<int>> res;
    if(!root) return res;
    bool flag = true;
    queue<TreeNode*> q;
    q.push(root);
    while(!q.empty()) {
        int n = q.size();
        vector<int> path;
        for(int i = 0; i < n; ++i) {
            TreeNode *node = q.front();
            q.pop();
            if(node->left) q.push(node->left);
            if(node->right) q.push(node->right);
            path.push_back(node->val);
        }
        if(flag) {
            res.push_back(path);
        }
        else {
            res.push_back(vector<int>(path.rbegin(), path.rend()));
        }
        flag = !flag;
    }
    return res;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值