代码随想录第14天

图解

1.二叉树的递归遍历:

前序遍历:

class Solution {
public:
    void traversal(TreeNode* cur, vector<int>& vec) {
        if (cur == NULL) return;
        vec.push_back(cur->val);    // 中
        traversal(cur->left, vec);  // 左
        traversal(cur->right, vec); // 右
    }
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> result;
        traversal(root, result);
        return result;
    }
};

后序遍历和中序遍历差不多。

注:return时返回上一层递归,输入值到数组的都是依靠vec.push_back(cur->val);每一组三角形(有三个节点组成)的顶都可以当成根节点,左为左节点,右为右节点,每一次递归都是换一个新三角形。

2. 二叉树的迭代遍历

前序遍历:

class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        stack<TreeNode*> st;
        vector<int> result;
        if (root == NULL) return result;
        st.push(root);
        while (!st.empty()) {
            TreeNode* node = st.top();                       // 中
            st.pop();
            result.push_back(node->val);
            if (node->right) st.push(node->right);           // 右(空节点不入栈)
            if (node->left) st.push(node->left);             // 左(空节点不入栈)
        }
        return result;
    }
};

 注:

1.TreeNode* 是结构体,存放val和左指针和右指针,传到st里面的是节点不是只有值

2.st.push(root);  root传进去的时整个二叉树的根节点。

后序遍历就是入栈的时候左和右反一下,变成中右左,在让vector反转就变成左右中了。

中序遍历:

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> result;
        stack<TreeNode*> st;
        TreeNode* cur = root;
        while (cur != NULL || !st.empty()) {
            if (cur != NULL) { // 指针来访问节点,访问到最底层
                st.push(cur); // 将访问的节点放进栈
                cur = cur->left;                // 左
            } else {
                cur = st.top(); // 从栈里弹出的数据,就是要处理的数据(放进result数组里的数据)
                st.pop();
                result.push_back(cur->val);     // 中
                cur = cur->right;               // 右
            }
        }
        return result;
    }
};

关于如何返回父节点,让cur=栈里面上一个进入的节点比如 :

            5

      4         6

  1     2

进栈的是541,cur=1的左节点是空开始弹出1,cur=1的右节点,是空,弹出4,这样就能返回父节点了。

3.二叉树的统一迭代法:

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> result;
        stack<TreeNode*> st;
        if (root != NULL) st.push(root);
        while (!st.empty()) {
            TreeNode* node = st.top();
            if (node != NULL) {
                st.pop(); // 将该节点弹出,避免重复操作,下面再将右中左节点添加到栈中
                if (node->right) st.push(node->right);  // 添加右节点(空节点不入栈)

                st.push(node);                          // 添加中节点
                st.push(NULL); // 中节点访问过,但是还没有处理,加入空节点做为标记。

                if (node->left) st.push(node->left);    // 添加左节点(空节点不入栈)
            } else { // 只有遇到空节点的时候,才将下一个节点放进结果集
                st.pop();           // 将空节点弹出
                node = st.top();    // 重新取出栈中元素
                st.pop();
                result.push_back(node->val); // 加入到结果集
            }
        }
        return result;
    }
};

看是看的懂,但是在弹出的时候他是一次while循环弹一个,如果要连续弹两个的话,在第一弹完后,把第2个先弹出去,在加回来后面再加一个null,这样就可以把他弹出去了。

注:如果用while循环一次性弹完会超时。

把节点加入栈的思路其实是每次都以三个节点为一次加循环,都从父节点的右孩子开始加到栈里面去

中序遍历是把所有节点都加完了,在从后面反向加到result里面,后序遍历也差不多是这个。但是前序遍历不是这样的思路,他是遇到一个父节点就把他加到result里面。(这段话讲不清还是自己模拟一边好了,听个大概就行)

这个统一迭代法他加节点的规律是和他遍历的方向是反的,比如中序遍历是左中右,而他加节点那一块的代码时右中左,其他的前序遍历,后续遍历,中序遍历一样。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值