面试准备3---------树遍历

1.树的基本遍历

//      1
//    2   3
//   4 5 6 7
public static void main(String[] args){
    Tree<Integer> root = new Tree<>(1);
    root.left =new Tree<>(2);
    root.left.left =new Tree<>(4);
    root.left.right =new Tree<>(5);
    root.right =new Tree<>(3);
    root.right.left =new Tree<>(6);
    root.right.right =new Tree<>(7);
    System.out.print("前序遍历:");
    preOrder(root);
    System.out.println();

    System.out.print("中序遍历:");
    inOrder(root);
    System.out.println();

    System.out.print("后序遍历:");
    postOrder(root);
    System.out.println();

    System.out.print("层序遍历:");
    levelOrder(root);
    System.out.println();

    System.out.print("前序遍历:");
    preOrderNoRecurisive(root);
    System.out.println();

    System.out.print("中序遍历:");
    inOrderNoRecurisive(root);
    System.out.println();

    System.out.print("后序遍历:");
    postOrderNoRecurisive(root);
    System.out.println();
}

public static class Tree<T>{
    private T val;
    private Tree<T> left;
    private Tree<T> right;
    public Tree(T val){
        this.val = val;
    }
}

//前序遍历
public static void preOrder(Tree<Integer> root){
    if(root == null){
        return;
    }
    System.out.print(root.val +"  ");
    preOrder(root.left);
    preOrder(root.right);

}

//前序遍历
public static void preOrderNoRecurisive(Tree<Integer> root){
    if(root == null){
        return;
    }

    //只要当前节点不为空或者栈非空,就入栈;当前节点若为空,就弹栈并指向右子树
    Stack<Tree<Integer>> stack = new Stack<>();
    Tree<Integer> cur = root;
    while(cur != null || !stack.isEmpty()){
        if(cur!=null){
            //遍历当前节点
            System.out.print(cur.val +"  ");
            //入栈
            stack.push(cur);
            cur = cur.left;
        }else{
            //弹栈
            cur = stack.pop().right;
        }
    }

}
//中序遍历
public static void inOrderNoRecurisive(Tree<Integer> root){
    if(root == null){
        return;
    }

    //只要当前节点不为空或者栈非空,就入栈;当前节点若为空,就弹栈并指向右子树
    Stack<Tree<Integer>> stack = new Stack<>();
    Tree<Integer> cur = root;
    while(cur != null || !stack.isEmpty()){
        if(cur!=null){
            //入栈
            stack.push(cur);
            cur = cur.left;
        }else{
            //遍历当前节点
            System.out.print(stack.peek().val +"  ");
            //弹栈
            cur = stack.pop().right;
        }
    }

}

//后序遍历
public static void postOrderNoRecurisive(Tree<Integer> root){
    if(root == null){
        return;
    }

    //需要判断上次访问的节点是位于左子树,还是右子树。
    //若是位于左子树,则需跳过根节点,先进入右子树,再回头访问根节点;
    //若是位于右子树,则直接访问根节点
    Stack<Tree<Integer>> stack = new Stack<>();
    Tree<Integer> cur = root;
    Tree<Integer> preVisited = null;//区分是左子树还是右子树返回的

    while(cur != null || !stack.isEmpty()){
        if(cur!=null){
            //入栈
            stack.push(cur);
            cur = cur.left;
        }else{

            //当前节点指向栈顶右子树
            cur = stack.peek().right;
            //判断右子树是否被访问过
            if(cur !=null && cur != preVisited){
                //右子树没有被访问过,就把右子树的所有左子树入栈
                stack.push(cur);
                cur = cur.left;
            }else{
                //右子树已经被访问过
                preVisited = stack.pop();
                //遍历当前节点
                System.out.print(preVisited.val +"  ");
                //弹栈
                cur = null;
            }

        }
    }

}


//中序遍历
public static void inOrder(Tree<Integer> root){
    if(root == null){
        return;
    }
    inOrder(root.left);
    System.out.print(root.val +"  ");
    inOrder(root.right);


}

//后序遍历
public static void postOrder(Tree<Integer> root){
    if(root == null){
        return;
    }
    postOrder(root.left);
    postOrder(root.right);
    System.out.print(root.val +"  ");
}

//层序遍历
public static void levelOrder(Tree<Integer> root){
    //队列存储元素
    Queue<Tree<Integer>> queue = new LinkedList<>();
    if(root == null){
        return;
    }
    Tree<Integer> temp = null;
    //根先入队列
    queue.offer(root);
    while(!queue.isEmpty()){
        //先取队头元素
        temp = queue.poll();
        //访问该元素
        if(temp !=null){
            System.out.print(temp.val +"  ");
            if(temp.left!=null){
                queue.offer(temp.left);
            }
            if(temp.right!=null){
                queue.offer(temp.right);
            }
        }

    }

}

注:二叉树后序遍历,将要被访问的节点的父节点均存储在栈里面,因此,弹栈就可以获取这条路径;

2.二叉树重建

public static void main(String[] args){
    int[] pre={1,2,4,5,3};
    int[] in={4,2,5,1,3};
    Tree root = construct(pre,in);

    System.out.print("前序遍历:");
    preOrder(root);
    System.out.println();

    System.out.print("中序遍历:");
    inOrder(root);
    System.out.println();

    System.out.print("后序遍历:");
    postOrder(root);
    System.out.println();
}

//重建二叉树
public static Tree construct(int[] preorder, int[] inorder){
    if(preorder == null || inorder == null || preorder.length == 0
            || inorder.length == 0 || preorder.length != inorder.length)
        return null;
    return constructCore(preorder, 0, inorder, 0, preorder.length);
}

public static Tree constructCore(int[] preorder, int preorder_start, int[] inorder, int inorder_start, int length){
    if(preorder == null || inorder == null || preorder.length == 0 || preorder.length != inorder.length)
        return null;
    if(0 >= length){
        return null;
    }
    int inorderRootIndex  = -1;
    //前序和中序获取根节点位置
    for(int i = inorder_start; i < inorder_start + length; i++){
        if(inorder[i] == preorder[preorder_start]){
            inorderRootIndex = i;
            break;
        }
    }

    int left_length = inorderRootIndex - inorder_start;

    //获取根节点
    Tree<Object> node = new Tree<>(preorder[preorder_start]);

    //递归构建左子树
    node.left = constructCore(preorder, preorder_start + 1, inorder, inorder_start, left_length);
    node.right = constructCore(preorder, preorder_start + left_length + 1, inorder,
                    inorderRootIndex + 1, length - left_length -1);

    return node;
}

3.中序遍历二叉树的下一个节点

//二叉树中序遍历的下一个节点
public static class TreeWithFatherPointer<T>{
    private T val;
    private TreeWithFatherPointer left;
    private TreeWithFatherPointer right;
    private TreeWithFatherPointer father;

    public TreeWithFatherPointer(T val){
        this.val = val;
    }
}

public static TreeWithFatherPointer getNext(TreeWithFatherPointer root){
    if(root == null){
        return null;
    }
    //只要有右子树,就循环查找右子树的最左子树
    if(root.right != null){
        root = root.right;
        while(root.left != null){
            root = root.left;
        }
        return root;
    }

    //没有右子树,就向上查找一个节点,满足该节点的父节点的左海子节点恰好是该节点,则该父节点就是下一个节点
    while(root.father !=null){
        if(root.father.left == root)
            return root.father;
        root = root.father;
    }
    return null;

}

public static void main(String [] args){
    //      1
    //     2  3
    //    4  5
    TreeWithFatherPointer<Integer> root = new TreeWithFatherPointer<>(1);
    root.left = new TreeWithFatherPointer(2);
    root.left.father = root;
    root.right = new TreeWithFatherPointer(3);
    root.right.father = root;

    root.left.left = new TreeWithFatherPointer(4);
    root.left.left.father = root.left.left;
    root.left.right = new TreeWithFatherPointer(5);
    root.left.right.father = root.left.right;

    System.out.println(getNext(root.left).val);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值