树的遍历 - 前/中/后/层 序遍历

2 篇文章 0 订阅
2 篇文章 0 订阅

树的遍历 - 前/中/后/层 序遍历

给你二叉树的根节点 root ,返回它节点值的 前/中/后/层 序遍历。

前/中/后序遍历

递归、迭代(DFS)、Morris遍历

/**
 * 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) {}
 * };
 */

递归

时间复杂度O(n)

平均空间复杂度O(logn),最坏O(n),为递归过程中隐式栈的开销

// 前序遍历 RAB
void traver_pre(vector<int> &ans, TreeNode *r) {
    if(r == nullptr) return ;
    ans.emplace_back(r->val);		// 前序遍历 - RAB
    traver_pre(ans, r->left);
    // ans.emplace_back(r->val);	// 中序遍历 - ARB
    traver_pre(ans, r->right);
    // ans.emplace_back(r->val);	// 后序遍历 - ABR
}
vector<int> preorderTraversal(TreeNode *root) {
    vector<int> ans;
    traver_pre(ans, root);
    return ans;
}

迭代 - 栈

时间复杂度O(n)

平均空间复杂度O(logn),最坏O(n),为递归过程中显式栈的开销

// 前序遍历 RAB
vector<int> preorderTraversal(TreeNode *root) {
    vector<int> ans{};
    stack<TreeNode*> st{};
    TreeNode *p = root;
    if(p) st.push(p);					// 中
    while(!st.empty()) {
        p = st.top();
        ans.emplace_back(p->val);		
        st.pop();
        if(p->right) st.push(p->right); // 右
        if(p->left) st.push(p->left);   // 左 
    }
    return ans;
}

// 中序遍历 - ARB
vector<int> inorderTraversal(TreeNode* root) {
    vector<int> ans{};
    stack<TreeNode*> st{};
    TreeNode *p=nullptr;
    if(root) st.push(root);
    while(!st.empty()) {
        p = st.top();
        if(p) {
            st.pop();
            if(p->right) st.push(p->right);	// 右
            st.push(p);						// 中
            st.push(nullptr);				
            if(p->left) st.push(p->left);	// 左
        }else {
            st.pop();
            ans.emplace_back(st.top()->val);
            st.pop();
        }
    }
    return ans;
}

// 后序遍历 - ABR
vector<int> postorderTraversal(TreeNode* root) {
    vector<int> ans{};
    stack<TreeNode*> st{};
    TreeNode *p=nullptr;
    if(root) st.push(root);					// 中
    while(!st.empty()) {
        p = st.top();
        if(p) {
            st.push(nullptr);				
            if(p->right) st.push(p->right);	// 右
            if(p->left) st.push(p->left);	// 左
        }else {
            st.pop();
            ans.emplace_back(st.top()->val);
            st.pop();
        }
    }
    return ans;
}

Morris 遍历

时间复杂度O(n),没有左子树的节点被访问一次,有左子树的被访问两次

空间复杂度O(1)

  1. 如果存在左子树,找到子树中最后访问的节点(根的左节点最右侧的节点)
    • 如果其未与根建立连接,则建立连接,代表第1个位置,只与根有关,表示开始遍历其左子树
    • 如果已与根建立连接,则释放连接,代表第3个位置,只与根有关,表示其左子树遍历完成
  2. 如果不存在左子树,开始遍历右子树
    • 代表第2、4个位置,分别可表示其父节点左右节点
    • 第2个位置:表示建立连接后,root向其左节点移动后,其不存在左节点的情况
    • 第4个位置:表示释放连接后,root向其右节点移动后,其不存在左节点的情况
// 前序遍历 RAB
vector<int> preorderTraversal(TreeNode *root) {
    vector<int> ans;
    TreeNode *p;
    while(root) {
        if(root->left) {    // 判断是否存在左子树
            p = root->left;
            while(p->right && p->right != root) p = p->right;
            if(!p->right) {     // 判断是否与根建立连接
                ans.emplace_back(root->val);    // 中 - 1
                p->right = root;
                root = root->left;
            }else {
                // ans.emplace_back(root->val); // 中 - 3
                root = root->right;
                p->right = nullptr;
            }
        }else {     // 不存在左子树,开始遍历右子树
            ans.emplace_back(root->val);    // 左 - 2、右 - 4
            root = root->right;
        }
    }
    return ans;
}

// 中序遍历 ARB
vector<int> inorderTraversal(TreeNode *root) {
    vector<int> ans;
    TreeNode *p;
    while(root) {
        if(root->left) {        // 存在左子树,找到子树中最后访问的节点(,将其与根建立连接)
            p = root->left;
            while(p->right && p->right != root) p = p->right;
            if(!p->right) {     // 未与根建立连接
                // ans.emplace_back(root->val);    // 中 - 1
                p->right = root;
                root = root->left;
            }else {
                ans.emplace_back(root->val); // 中 - 3
                root = root->right;
                p->right = nullptr;
            }
        }else {     // 不存在左子树,开始遍历右子树
            ans.emplace_back(root->val);    // 左 - 2、右 - 4
            root = root->right;
        }
    }
    return ans;
}

// 后序遍历 RBA->ABR
vector<int> postorderTraversal(TreeNode* root) {
    vector<int> ans;
    TreeNode *p;
    while(root) {
        if(root->right) {    // 判断是否存在左子树
            p = root->right;
            while(p->left && p->left != root) p = p->left;
            if(!p->left) {     // 判断是否与根建立连接
                ans.emplace_back(root->val);    // 中 - 1
                p->left = root;
                root = root->right;
            }else {
                // ans.emplace_back(root->val); // 中 - 3
                root = root->left;
                p->left = nullptr;
            }
        }else {     // 不存在左子树,开始遍历右子树
            ans.emplace_back(root->val);    // 左 - 2、右 - 4
            root = root->left;
        }
    }
    reverse(ans.begin(), ans.end());
    return ans;
}

层序遍历

递归、迭代(BFS)

递归

void traver_level(vector<vector<int>> &ans, TreeNode *p, int level) {
    if(p == nullptr) return;
    if(ans.size() == level) ans.emplace_back(vector<int>());
    ans[level].emplace_back(p->val);
    traver_level(ans, p->left, level+1);
    traver_level(ans, p->right, level+1);
}
vector<vector<int>> levelOrder(TreeNode* root) {
    vector<vector<int>> ans{};
    traver_level(ans, root, 0);
    return ans;
}

迭代 - 队列

vector<vector<int>> levelOrder(TreeNode* root) {
    vector<vector<int>> ans{};
    queue<TreeNode*> que{};
    if(root) que.push(root);
    while(!que.empty()) {
        int n = que.size();
        ans.emplace_back(vector<int>());
        while(n--) {
            auto p = que.front();
            que.pop();
            ans.back().emplace_back(p->val);
            if(p->left) que.push(p->left);
            if(p->right) que.push(p->right);
        }
    }
    return ans;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
可以通过先列和列重建二叉,然后对重建后的二叉进行后和层次遍即可。 具体步骤如下: 1. 根据先列确定根结点。 2. 在找到根结点所在位置,根结点左边的列是左子列,右边的列是右子列。 3. 通过左子列长度确定先左子的先列,右子的先列为剩余部分。 4. 递归处理左子和右子,重建二叉。 5. 对重建后的二叉进行后和层次遍。 下面是 Python 代码实现: ```python class TreeNode: def __init__(self, val): self.val = val self.left = None self.right = None def buildTree(preorder, inorder): if not preorder or not inorder: return None root = TreeNode(preorder[0]) inorderIndex = inorder.index(preorder[0]) leftInorder = inorder[:inorderIndex] rightInorder = inorder[inorderIndex+1:] leftPreorder = preorder[1:len(leftInorder)+1] rightPreorder = preorder[len(leftInorder)+1:] root.left = buildTree(leftPreorder, leftInorder) root.right = buildTree(rightPreorder, rightInorder) return root def postorderTraversal(root): if not root: return [] stack = [root] res = [] while stack: node = stack.pop() res.append(node.val) if node.left: stack.append(node.left) if node.right: stack.append(node.right) return res[::-1] def levelOrder(root): if not root: return [] queue = [root] res = [] while queue: level = [] for i in range(len(queue)): node = queue.pop(0) level.append(node.val) if node.left: queue.append(node.left) if node.right: queue.append(node.right) res.append(level) return res preorder = [1, 2, 4, 5, 3, 6, 7] inorder = [4, 2, 5, 1, 6, 3, 7] root = buildTree(preorder, inorder) print(postorderTraversal(root)) # 输出后列 [4, 5, 2, 6, 7, 3, 1] print(levelOrder(root)) # 输出层次遍列 [[1], [2, 3], [4, 5, 6, 7]] ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

solmp

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值