打赏

[******] 树问题:普通二叉树的创建与遍历

1. 二叉树的创建

 

 

String pre_str = "1,2,4,8,-1,-1,9,-1,-1,5,-1,-1,3,6,-1,10,-1,-1,7,-1,-1";//先序输入
String post_str = "-1,-1,8,-1,-1,9,4,-1,-1,5,2,-1,-1,-1,10,6,-1,-1,7,3,1";//后序输入
String level_str = "1,2,3,4,5,6,7,8,9,-1,-1,-1,10,-1,-1";//层次输入
int[] in = {8,4,9,2,5,1,6,10,3,7}; //中序
int[] pre = {1,2,4,8,9,5,3,6,10,7}; //先序
int[] post = {8,9,4,5,2,10,6,7,3,1}; //后序
String input = "1(2(4(8,9),5),3(6(,10),7))";//括号表达式输入
    static class TreeNode{
        int value;
        TreeNode left;
        TreeNode right;
        public TreeNode(int value){
            this.value = value;
        }
    }

1.1 前序遍历创建二叉树

核心思路:根左右,从左往右读

  /**先序方法1*/
    public static TreeNode pre_buildBTree1(InputChar ic, int flag) {
        int x = ic.pregetChar();
        if (x == flag)
            return null;
        TreeNode t = new TreeNode(x);
        t.left = pre_buildBTree1(ic,flag);
        t.right = pre_buildBTree1(ic,flag);
        return t;
    }
    /**先序方法2*/
    public static int position = -1;
    public static TreeNode pre_buildBTree2(int[] array, int flag) {
        int x = array[++position];
        TreeNode node = null;
        if(position < array.length && x != flag){
            node = new TreeNode(x);
            node.left = pre_buildBTree2(array,flag);
            node.right = pre_buildBTree2(array,flag);
        }
        return node;
    }

  /***用于获取值 */
    static class InputChar {
        private int[] array;
        private int pos = 0;

        public InputChar(int[] array,int pos) {
            this.array = array;
            this.pos = pos;
        }
        public int pregetChar() {
            int i = pos;
            pos++;
            return array[i];
        }
        public int postgetChar() {
            int i = pos;
            pos--;
            return array[i];
        }
    }

    public static void main(String[] args) {
        /***********************先序创建二叉树***********************/
        String pre_str = "1,2,4,8,-1,-1,9,-1,-1,5,-1,-1,3,6,-1,10,-1,-1,7,-1,-1";//先序
        String[] array = pre_str.split(",");
        int [] intarray = new int[array.length];
        for (int i = 0; i < intarray.length; i++) {
            intarray[i]=Integer.valueOf(array[i]);
        }
        //第一种先序遍历创建二叉树方法
        InputChar inint = new InputChar(intarray,0);
        TreeNode root1 = pre_buildBTree1(inint,-1);
        //第二种先序遍历创建二叉树方法
        position = -1;
        TreeNode root2 = pre_buildBTree2(intarray,-1);
        root1 = root2;
   }    

 

1.2 后序遍历创建二叉树

核心思路:左右根,从右往左读  

  /**后序方法1*/
    public static TreeNode post_buildBTree1(InputChar ic, int flag) {
        int x = ic.postgetChar();
        if (x == flag)
            return null;
        TreeNode t = new TreeNode(x);//根
        t.right = post_buildBTree1(ic,flag);//右
        t.left = post_buildBTree1(ic,flag);//左
        return t;
    }
    /**后序方法2*/
    public static TreeNode post_buildBTree2(int[] array, int flag) {
        int x = array[--position];
        TreeNode node = null;
        if(position >= 0 && x != flag){
            node = new TreeNode(x);
            node.right = post_buildBTree2(array,flag);
            node.left = post_buildBTree2(array,flag);
        }
        return node;
    }
  /***用于获取值 */
    static class InputChar {
        private int[] array;
        private int pos = 0;

        public InputChar(int[] array,int pos) {
            this.array = array;
            this.pos = pos;
        }
        public int pregetChar() {
            int i = pos;
            pos++;
            return array[i];
        }
        public int postgetChar() {
            int i = pos;
            pos--;
            return array[i];
        }
    }
    public static void main(String[] args) {
     /***********************后序创建二叉树***********************/
        String post_str = "-1,-1,8,-1,-1,9,4,-1,-1,5,2,-1,-1,-1,10,6,-1,-1,7,3,1";//后序
        String[] array2 = post_str.split(",");
        int [] intarray2 = new int[array.length];
        for (int i = 0; i < intarray.length; i++) {
            intarray2[i]=Integer.valueOf(array2[i]);
        }
        //第一种先序遍历创建二叉树方法
        InputChar inint2 = new InputChar(intarray2,intarray2.length-1);
        TreeNode root3 = post_buildBTree1(inint2,-1);
        root1 = root3;
        //第二种先序遍历创建二叉树方法
        position = intarray2.length;
        TreeNode root4 = post_buildBTree2(intarray2,-1);
        root1 = root4;    
    }

 

1.3 层次遍历创建二叉树

核心思路:利用二叉树的性质,左孩子=2*i,右孩子=2*i+1

  /**层次遍历创建二叉树*/
    public static TreeNode level_buildBTree(int[]array,int flag){
        int len = array.length;
        //将数组转成list
        LinkedList<TreeNode> list = new LinkedList<>();
        for (int i = 0; i < len; i++) {
            list.add(new TreeNode(array[i]));
        }
        //开始构建树
        for (int i = 0; i < len/2; i++) {
            list.get(i).left = list.get(2*i+1).value!=flag?list.get(2*i+1):null;
            //记得处理最后一个父节点(len/2-1),因为有可能没有右孩子。
            if(i<len/2-1 ||(i==len/2-1&& len%2!=0)){
                list.get(i).right = list.get(2*i+2).value!=flag?list.get(2*i+2):null;
            }
        }
        return list.get(0);
    }
    public static void main(String[] args) {
    /***********************层次创建二叉树***********************/
        String level_str = "1,2,3,4,5,6,7,8,9,-1,-1,-1,10,-1,-1";//层次
        String[] array1 = level_str.split(",");
        int len = array1.length;
        int[] intlevelarray = new int[len];
        for (int i = 0; i < len; i++) {
            intlevelarray[i] = Integer.valueOf(array1[i]);
        }
        TreeNode  root5 = level_buildBTree(intlevelarray,-1);
        root1 = root5;
    }

 

1.4 前序和中序创建二叉树

 

    /***从中序与先序遍历序列构造二叉树**/
    public static TreeNode inpre_buildTree(int[] preOrder, int[] inorder) {
        TreeNode root = inpre_buildTreehelper(preOrder, 0, preOrder.length - 1, inorder, 0, inorder.length - 1);
        return root;
    }
    private static TreeNode inpre_buildTreehelper(int[] preOrder, int preStart, int preEnd, int[] inorder, int inStart, int inEnd) {
        if (preStart > preEnd || inStart > inEnd) {
            return null;
        }
        int x = preOrder[preStart];
        TreeNode root = new TreeNode(x);
        for (int i = inStart; i <= inEnd; i++)
            if (inorder[i] == x) {
                root.left = inpre_buildTreehelper(preOrder, preStart + 1, preStart + i - inStart, inorder, inStart, i - 1);
                root.right = inpre_buildTreehelper(preOrder, i - inStart + preStart + 1, preEnd, inorder, i + 1, inEnd);
                break;
            }
        return root;
    }
    public static void main(String[] args) {
    /***********************从中序与先序遍历序列构造二叉树***********************/
        int[] in = {8,4,9,2,5,1,6,10,3,7};
        int[] pre = {1,2,4,8,9,5,3,6,10,7};
        root1 = inpre_buildTree(pre, in);
    }

 

1.5 后续和中序创建二叉树

 

/***从中序与后序遍历序列构造二叉树**/
public static TreeNode inpost_buildTree(int[] inorder, int[] postorder) {
    return inpost_buildTreehelper(postorder, 0, postorder.length - 1, inorder, 0, inorder.length - 1);
}
    
private static TreeNode inpost_buildTreehelper(int[] postorder,int postStart, int postEnd, int[] inorder,  int inStart, int inEnd){
    if (postStart > postEnd || inStart > inEnd) {
       return null;
    }
    int x = postorder[postEnd];
    TreeNode root = new TreeNode(x);
    for (int i = inStart; i <= inEnd; i++)
        if (inorder[i] == x) {
            root.left = inpost_buildTreehelper(postorder, postStart, postEnd-(inEnd - i)-1, inorder, inStart, i - 1);
            root.right = inpost_buildTreehelper(postorder, postEnd-(inEnd - i), postEnd-1, inorder, i + 1, inEnd);
            break;
        }
    return root;
}
public static void main(String[] args) { int[] in = {8,4,9,2,5,1,6,10,3,7}; int[] post = {8,9,4,5,2,10,6,7,3,1}; root1 = inpost_buildTree(in, post); }

 

1.6 括号表达式创建二叉树

//括号表达式构建二叉树
static TreeNode kuohao__buildTree(String input) {
    char[] str = input.toCharArray();
    TreeNode root = null;
    TreeNode p = null;
    Stack<TreeNode> s = new Stack<TreeNode>();
    int i = 0;
    int k = 0;
    char ch = str[i];
    while(i<str.length){
        switch(ch){
            case '(':{
                s.push(p);//括号左边的是父亲,入栈
                k = 1;//括号右面的是左孩子
                break;
            }
            case ',':{
                k = 2;//逗号右边的是有孩子
                break;
            }
            case ')':{
                s.pop();//表示该节点的左右孩子已经确定,出栈
                break;
            }
            default:{
                int count = 0;
                boolean flag = false;
                while(i<str.length && (str[i] + "").matches("[0-9]")){
                    count = count * 10 + (str[i]-'0');
                    i++;
                    flag = true;
                }
                if (flag = true) i--;//为了判断数字,多加了一次,所以减去
                p = new TreeNode(count);//保存多位数字
                if(root==null){
                    root = p;//保存根节点
                }else{
                    if(k==1){
                        s.peek().left = p;
                    }else if(k==2){
                        s.peek().right = p;
                    }
                }
                break;
            }
        }
        i++;
        if(i<str.length){
            ch = str[i];
        }
    }
    return root;
}

public static void main(String[] args) {
    /***********************括号表达式构造二叉树***********************/
    String input = "1(2(4(8,9),5),3(6(,10),7))";
    TreeNode root6 = kuohao__buildTree(input);
}

 

2. 二叉树的遍历

2.1 前序遍历(根左右)

/***递归先序遍历*/
    public static void preOrder(TreeNode root,List<TreeNode> preorder){
        if(root!=null){
            preorder.add(root);
            preOrder(root.left,preorder);
            preOrder(root.right,preorder);
        }
    }

/***非递归先序遍历*/
    public static List<TreeNode> preOrderT(TreeNode root){
        List<TreeNode> list =  new LinkedList<TreeNode>();
        Stack<TreeNode> stack = new Stack<TreeNode>();
        if(root!=null){
            stack.push(root);
            while(!stack.empty()){
                TreeNode cur = stack.pop();
                list.add(cur);
                if(cur.right!=null) stack.push(cur.right);
                if(cur.left!=null) stack.push(cur.left);
            }
        }
        return list;
    }
    

public static void main(String[] args) {      System.out.println("==========递归先序遍历========="); List<TreeNode> preorder = new LinkedList<TreeNode>(); preOrder(root1,preorder);//递归先序遍历 printNonLevel(preorder);//打印      System.out.println("==========非递归先序遍历========="); List<TreeNode> preorderT = preOrderT(root1);//非递归先序遍历 printNonLevel(preorderT);//打印 } /***************************打印*************************/ /** * 打印一维链表(先序,中序,后序) * @param List<TreeNode> treeNode */ public static void printNonLevel(List<TreeNode> treeNode){ for (int i = 0; i < treeNode.size(); i++) { System.out.print(treeNode.get(i).value+" "); } System.out.println(); }

 

2.2 后序遍历(左右根)

addFirst

/***递归后序遍历*/
    public static void postOrder(TreeNode root,List<TreeNode> postorder){
        if(root!=null){
            postOrder(root.left,postorder);
            postOrder(root.right,postorder);
            postorder.add(root);
        }
    }
/***非递归后序遍历*/
    public static List<TreeNode> postOrderT(TreeNode root){
        LinkedList<TreeNode> list =  new LinkedList<TreeNode>();
        Stack<TreeNode> stack = new Stack<TreeNode>();
        if(root!=null){
            stack.push(root);
            while(!stack.empty()){
                TreeNode cur = stack.pop();
                list.addFirst(cur);
                if(cur.left!=null) stack.push(cur.left);
                if(cur.right!=null) stack.push(cur.right);
            }
        }
        return list;
    }
public static void main(String[] args) {
     System.out.println("==========递归后序遍历=========");
        List<TreeNode> postorder = new LinkedList<TreeNode>();
        postOrder(root1,postorder);//递归后序遍历
        printNonLevel(postorder);//打印
       System.out.println("==========非递归后序遍历=========");
        List<TreeNode> postorderT = postOrderT(root1);//递归后序遍历
        printNonLevel(postorderT);//打印  
}
/***************************打印*************************/
    /**
     * 打印一维链表(先序,中序,后序)
     * @param List<TreeNode>  treeNode
     */
    public static void printNonLevel(List<TreeNode> treeNode){
        for (int i = 0; i < treeNode.size(); i++) {
            System.out.print(treeNode.get(i).value+" ");
        }
        System.out.println();
    }

 

2.3 中序遍历(左根右)

    /***递归中序遍历*/
    public static void inOrder(TreeNode root, List<TreeNode> inorder){
        if(root!=null){
            inOrder(root.left,inorder);
            inorder.add(root);
            inOrder(root.right,inorder);
        }
    }

    /***非递归中序遍历*/
    public static List<TreeNode> inOrderT(TreeNode root){
        List<TreeNode> list =  new LinkedList<TreeNode>();
        Stack<TreeNode> stack = new Stack<TreeNode>();
        TreeNode cur = root;
        while(cur!=null || !stack.empty()){
            while(cur!=null){
                stack.push(cur);
                cur = cur.left;
            }
            cur = stack.pop();
            list.add(cur);
            cur = cur.right;
        }
        return list;
    }
public static void main(String[] args) {
      System.out.println("==========递归中遍历=========");
        List<TreeNode> inorder = new LinkedList<TreeNode>();
        inOrder(root1,inorder);//递归中序遍历
        printNonLevel(inorder);//打印
        System.out.println("==========非递归中序遍历=========");
        List<TreeNode> inorderT = inOrderT(root1);//非递归中序遍历
        printNonLevel(inorderT);//打印
 
}
/***************************打印*************************/
    /**
     * 打印一维链表(先序,中序,后序)
     * @param List<TreeNode>  treeNode
     */
    public static void printNonLevel(List<TreeNode> treeNode){
        for (int i = 0; i < treeNode.size(); i++) {
            System.out.print(treeNode.get(i).value+" ");
        }
        System.out.println();
    }

 

2.4 广度优先遍历(层次遍历)

 

/***广度优先遍历或者层次遍历*/
    public static List<List<TreeNode>> levelOrder(TreeNode root) {
        List<List<TreeNode>> res = new LinkedList<>();
        if (root == null) {
            return res;
        }
        levelOrderHelper(res, root, 0);
        return res;
    }

    /**二叉树的深度*/
    private static void levelOrderHelper(List<List<TreeNode>> res, TreeNode root, int depth) {
        if (root == null) {
            return;
        }
        if (res.size() <= depth) {
            res.add(new LinkedList<>());// 当前层的第一个节点,需要 new 一个 list 来存当前层.
        }
        res.get(depth).add(root);// depth 层,把当前节点加入
        // 递归的遍历下一层.
        levelOrderHelper(res, root.left, depth + 1);
        levelOrderHelper(res, root.right, depth + 1);
    }
/**非递归 广度优先遍历或者层次遍历,用队列实现层次遍历*/ public static List<List<TreeNode>> levelOrderT(TreeNode root) { if(root == null) return new ArrayList<>(); List<List<TreeNode>> list = new ArrayList<>();
     if(root == null) return list; Queue
<TreeNode> queue = new LinkedList<TreeNode>(); queue.offer(root); while(!queue.isEmpty()){ int count = queue.size(); List<TreeNode> levellist = new ArrayList<TreeNode>(); while(count > 0){ TreeNode node = queue.poll(); levellist.add(node); if(node.left != null) queue.offer(node.left); if(node.right != null) queue.offer(node.right); count--; } list.add(levellist); } return list; }
public static void main(String[] args) { System.out.println("==========递归广度优先遍历 OR 层次遍历========="); List<List<TreeNode>> levelOrder = levelOrder(root1); printLevel(levelOrder); System.out.println("==========非递归层次遍历========="); List<List<TreeNode>> levelOrderT = levelOrderT(root1); printLevel(levelOrderT); }
/** * 打印二维链表(层次) * @param List<List<TreeNode>> treeNode */ public static void printLevel(List<List<TreeNode>> levelOrder){ for (int i = 0; i < levelOrder.size(); i++) { for (int j = 0; j < levelOrder.get(i).size(); j++) { System.out.print(levelOrder.get(i).get(j).value +" "); } System.out.println(); } }

 

2.4 深度优先遍历

 /*** 深度优先遍历*/
    public static void dfs(TreeNode node, List<List<TreeNode>> dfsResult, List<TreeNode> list) {
        if (node == null)
            return;
        if (node.left == null && node.right == null) {
            list.add(node);
            dfsResult.add(new ArrayList<>(list));//不能直接将list存入,需要新建一个list来实现,防止后序操作影响
            list.remove(list.size() - 1);//将其最后一个存的节点删掉回溯
        }
        list.add(node);
        dfs(node.left, dfsResult, list);
        dfs(node.right, dfsResult, list);
        list.remove(list.size() - 1);
    } 

public static void main(String[] args) {
        System.out.println("==========非递归层次遍历=========");
        List<List<TreeNode>> levelOrderT = levelOrderT(root1);
        printLevel(levelOrderT);
    }

    /**
     * 打印二维链表(层次)
     * @param List<List<TreeNode>> treeNode
     */
    public static void printLevel(List<List<TreeNode>> levelOrder){
        for (int i = 0; i < levelOrder.size(); i++) {
            for (int j = 0; j < levelOrder.get(i).size(); j++) {
                System.out.print(levelOrder.get(i).get(j).value +" ");
            }
            System.out.println();
        }
    }

 

posted @ 2019-09-02 15:41  海米傻傻  阅读(364)  评论(0编辑  收藏  举报