一道满二叉树遍历的面试题

前提

1、二棵满二叉树
2、每棵二叉树包括,左右节点,父节点指针,值
3、二棵二叉树的根节点的父分别指向另外一棵二叉树的根节点

问题:

将二棵二叉树当成一个集合来处理,从其中的任意一个节点出发,遍历所有节点
要求:
1、集合中每个一个节点访问且只能访问一次
2、遍历过程不允许new出新对象和全局变量
3、遍历是只读行为,不能更改树上任何一个节点的值

对应代码:

在这里插入代码片
```class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode parent;

    TreeNode(int val) {
        this.val = val;
        left = right = parent = null;
    }

    TreeNode(TreeNode parent,int val) {
        this.val = val;
        this.parent = parent;
    }
}

class MutualParentTree {

    public static TreeNode buildBinaryTree(int height, int start) {
        TreeNode node = new TreeNode(start);
        fillTree(node, 1, height - 1, start);
        return node;
    }

    public static void fillTree(TreeNode node, int level, int remain, int val) {
        if (remain <= 0) return;
        node.left = new TreeNode(node,val * 2);
        fillTree(node.left, level + 1, remain - 1, val * 2);
        node.right = new TreeNode(node,val * 2 + 1);
        fillTree(node.right, level + 1, remain - 1, val * 2 + 1);
    }

    /**
     * 查找指定值的节点,从start节点开始,允许访问父节点一次
     * @param start      起始节点
     * @param target    目标值
     * @param allowParent 是否允许访问父节点
     * @return 找到的节点,若不存在则返回null
     */
    public static TreeNode findNode(TreeNode start, int target, boolean allowParent) {
        if (start == null) return null;
        if (start.val == target) return start;

        // 优先搜索左子树
        TreeNode leftResult = findNode(start.left, target, true);
        if (leftResult != null) return leftResult;

        // 再搜索右子树
        TreeNode rightResult = findNode(start.right, target, true);
        if (rightResult != null) return rightResult;
        return null;
    }
}

public class TreeTraversal {
        public static void main(String[] args) {
            // 生成两棵四层满二叉树(1-15 和 1001-1015)
            TreeNode root1 = MutualParentTree.buildBinaryTree(4, 1);
            TreeNode root2 = MutualParentTree.buildBinaryTree(4, 1);

            // 建立双向父指针循环
            root1.parent = root2;
            root2.parent = root1;

            //test 1
            System.out.println("start");
            TreeNode searchNode = MutualParentTree.findNode(root1,5,true);
            traverse(searchNode);
            // 假设已构建好root1和root2
            System.out.println("end");

            //test 2
            //traverse(root1);
        }

    /**
     * 需要堆栈上传递很多桩体
     * @param node
     */
    private static void traverse(TreeNode node) {
        if(node.parent.parent == node) {
            //根目录特殊处理
            System.out.println("travel init by root!");
            traverseTree(node);
            traverseTree(node.parent);
        }else{
            //正常遍历
            traverseTree(node);
            if (node.parent!=null){
                traverseTreePath(node,node.parent,true);
            }
        }
    }

    public static  void traverseTreePath(TreeNode node,TreeNode parentNode){
        if (node == null || parentNode==null) return;
        System.out.println("traverseTreePath:" + parentNode.val + " ");
        //非根目录
        if (node.parent != node) {
            if (parentNode.left == node) {
                //遍历right及父left
                traverseTree(node.parent.right);
                traverseTreePath(node.parent,node.parent.parent);
            } else if(parentNode.right == node) {
                //遍历left以及父right
                traverseTree(node.parent.left);
                traverseTreePath(node.parent,node.parent.parent);
            }else if(parentNode.parent == node){
                System.out.println("change root!");
                traverseTree(node.parent);
            }
        }
    }

    public static  void traverseTree(TreeNode node){
        if (node == null) return;
        System.out.println("traverseTree:"+node.val + " ");

        // 处理左子树,传入当前节点作为父节点以防止回溯
        traverseTree(node.left);

        // 处理右子树,同样传入当前节点作为父节点
        traverseTree(node.right);
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小小她爹

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

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

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

打赏作者

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

抵扣说明:

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

余额充值