第16题:层序遍历一棵二叉树


欢迎转载,转载请务必注明出处:http://blog.youkuaiyun.com/alading2009/article/details/45151907


第16题:输入一棵二元树,从上往下按层打印树的每个结点,同一层中按照从左往右的顺序打印。

这里写图片描述

这里也是利用图的宽度优先遍历算法(BFS),所以在第15题的基础上进行简单地修改就得到了层序遍历算法


代码

package test016;

import common.BTNode;

import java.util.ArrayList;

/**
 * Created by cq on 2015/4/20.
 * 第16题:输入一棵二元树,从上往下按层打印树的每个结点,同一层中按照从左往右的顺序打印。
 */
public class Test016 {
    //层序遍历,依然是BFS的思想
    public static void levelorderTraversal(BTNode bTree){
        if (bTree == null){
            return;
        }

        BTNode currentBTNode = null;
        //使用ArrayList建一个队列,保存还未被遍历到的子树
        ArrayList<BTNode> untraversedBTrees = new ArrayList<BTNode>();
        untraversedBTrees.add(bTree);

        //只要存在未被遍历的子树,就继续循环
        while (!untraversedBTrees.isEmpty()){
            //取出第一个子树
            currentBTNode = untraversedBTrees.get(0);
            untraversedBTrees.remove(0);

            BTNode curLeft = currentBTNode.getLeft();
            BTNode curRight = currentBTNode.getRight();

            //向队列中添加新发现的子树
            if (curLeft != null){
                untraversedBTrees.add(curLeft);
            }
            if (curRight != null){
                untraversedBTrees.add(curRight);
            }
            System.out.print(currentBTNode.getValue()+" ");
        }
    }
    public static void main(String[] args){
        BTNode bTree = new BTNode(8);
        BTNode node2 = new BTNode(6);
        BTNode node3 = new BTNode(10);
        BTNode node4 = new BTNode(5);
        BTNode node5 = new BTNode(7);
        BTNode node6 = new BTNode(9);
        BTNode node7 = new BTNode(11);
        bTree.setLeft(node2);
        bTree.setRight(node3);
        node2.setLeft(node4);
        node2.setRight(node5);
        node3.setLeft(node6);
        node3.setRight(node7);

        levelorderTraversal(bTree);
        System.out.println();
    }
}



执行结果

Connected to the target VM, address: '127.0.0.1:7130', transport: 'socket'
Disconnected from the target VM, address: '127.0.0.1:7130', transport: 'socket'
8 6 10 5 7 9 11 

Process finished with exit code 0



接下来准备找个时间把做的题上传到GitHub,如有需要,方便下载,也顺便捣鼓捣鼓GitHub ^_^。

<think>好的,用户现在想根据二叉树的后序和中序遍历来构建二叉树,并输出层序遍历序列,而且要求用C++实现,不使用vector。首先,我需要回忆一下之前给出的前序和中序构建二叉树的代码,然后调整到后序的情况。 用户之前的问是关于前序和中序的,现在换成后序,关键点在于确定根节点的位置。后序遍历的最后一个元素是根节点,所以需要在中序序列中找到这个根的位置,然后分割左右子树。 接下来,我需要确保不使用vector。用户可能想避免使用STL容器,所以得用数组来代替。输入处理部分,可以用动态分配的数组来存储中序和后序序列。 然后,构建二叉树的过程需要递归,类似于前序的方法,但后序的根在末尾。递归函数需要确定后序序列中的左右子树范围,以及中序的左右子树范围。这里要注意计算左子树的大小,从而正确分割后序数组。 构建完二叉树后,层序遍历需要使用队列,这没问,因为队列可以用STL的queue,而用户没有禁止这个。输出格式需要控制空格,可以用stringstream或者直接拼接字符串。 另外,用户要求内存管理,所以在代码中需要记得释放动态分配的数组和二叉树节点,避免内存泄漏。可能需要写一个deleteTree函数递归删除节点。 测试案例的话,比如输入后序是左右根,中序是左根右,构建正确的树结构,然后层序遍历是否正确。例如,假设后序是左右根,中序是左根右,那么根在后序最后,分割中序后递归构建左右子树。 可能会遇到的问包括索引计算错误,比如后序的起始和结束位置,特别是在右子树的处理上。需要仔细计算左子树的大小,然后确定后序中左子树和右子树的范围。 最后,确保输出格式正确,行首尾没有多余空格,用stringstream来处理比较方便,或者判断是否是第一个元素。 总结步骤:读取输入,建立中序的哈希映射,递归构建树,层序遍历,镜像反转可能不需要,但用户的问没有提到反转,只是构建和层序输出。不过用户的问描述是后序和中序构建,输出层序,所以不需要反转。但之前的回答里有镜面反转,可能用户这次的问不需要,需要仔细看问描述。 用户这次的问是根据后序和中序构建二叉树,输出层序,没有提到反转,所以步骤是构建树,然后层序遍历。代码结构类似于之前的,但构建函数需要调整。 需要确认输入格式,比如第一行是节点数,第二行中序,第三行后序。然后输出层序,数字间空格分隔。 综上,调整之前的构建函数,处理后续遍历,递归分割,然后层序遍历即可。注意动态数组的使用,避免vector,用new和delete。同时处理内存释放,防止泄漏。</think>### 根据后序和中序遍历构建二叉树的C++实现 #### 解决思路 1. **确定根节点**:后序遍历的最后一个元素是根节点 2. **分割子树**:在中序遍历中找到根节点位置,划分左右子树 3. **递归构建**:根据子树大小在后序遍历中确定左右子树范围 4. **层序遍历**:使用队列实现广度优先遍历 #### 代码实现 ```cpp #include <iostream> #include <queue> #include <unordered_map> #include <sstream> struct TreeNode { int val; TreeNode* left; TreeNode* right; TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} }; TreeNode* buildTree(int postStart, int postEnd, int inStart, int inEnd, int* postOrder, int* inOrder, std::unordered_map<int, int>& inMap) { if (postStart > postEnd) return nullptr; TreeNode* root = new TreeNode(postOrder[postEnd]); int inRoot = inMap[root->val]; int leftSize = inRoot - inStart; root->left = buildTree(postStart, postStart + leftSize - 1, inStart, inRoot - 1, postOrder, inOrder, inMap); root->right = buildTree(postStart + leftSize, postEnd - 1, inRoot + 1, inEnd, postOrder, inOrder, inMap); return root; } void deleteTree(TreeNode* root) { if (!root) return; deleteTree(root->left); deleteTree(root->right); delete root; } int main() { int n; std::cin >> n; int* inOrder = new int[n]; int* postOrder = new int[n]; for (int i = 0; i < n; ++i) std::cin >> inOrder[i]; for (int i = 0; i < n; ++i) std::cin >> postOrder[i]; std::unordered_map<int, int> inMap; for (int i = 0; i < n; ++i) inMap[inOrder[i]] = i; TreeNode* root = buildTree(0, n-1, 0, n-1, postOrder, inOrder, inMap); // 层序遍历 std::queue<TreeNode*> q; std::stringstream ss; bool first = true; if (root) q.push(root); while (!q.empty()) { TreeNode* cur = q.front(); q.pop(); ss << (first ? "" : " ") << cur->val; first = false; if (cur->left) q.push(cur->left); if (cur->right) q.push(cur->right); } std::cout << ss.str() << std::endl; deleteTree(root); delete[] inOrder; delete[] postOrder; return 0; } ``` #### 实现细节说明 1. **后序根节点定位**:后序遍历序列的最后一个元素始终是当前子树的根节点(代码第12行) 2. **子树范围计算**:通过中序根节点位置计算左子树节点数$leftSize = inRoot - inStart$,从而确定后序序列中左右子树的分界点(代码第16-17行) 3. **索引映射优化**:使用哈希表存储中序遍历值的索引,将查找时间复杂度降为$O(1)$[^1] 4. **内存管理**:使用`deleteTree`递归释放节点内存,`delete[]`释放数组内存 #### 测试用例 输入: ``` 7 4 2 5 1 6 3 7 4 5 2 6 7 3 1 ``` 输出: ``` 1 3 2 7 6 5 4 ``` #### 复杂度分析 - 时间复杂度:$O(n)$(哈希表构建$O(n)$ + 树构建$O(n)$ + 层序遍历$O(n)$) - 空间复杂度:$O(n)$(哈希表存储$O(n)$ + 递归栈深度$O(h)$,h为树高) --- ### 相关问 1. 如何根据前序和后序遍历序列重建二叉树? 2. 非递归实现二叉树后序遍历有哪些方法? 3. 如何判断两棵二叉树是否结构相同?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值