您的位置:首页 > 编程语言 > Java开发

java实现二叉树的创建及5种遍历

2016-10-10 22:30 525 查看
Java实现的数组创建二叉树以及递归先序遍历,递归中序遍历,递归后序遍历,非递归前序遍历,非递归中序遍历,非递归后序遍历,深度优先遍历,广度优先遍历8种遍历方式:

package myTest;  

  

import java.util.ArrayList;  

import java.util.LinkedList;  

import java.util.List;  

import java.util.Stack;  

  

public class myClass {  

      

    public static void main(String[] args) {  

        // TODO Auto-generated method stub  

        myClass tree = new myClass();  

        int[] datas = new int[]{1,2,3,4,5,6,7,8,9};  

        List<Node> nodelist = new LinkedList<>();  

        tree.creatBinaryTree(datas, nodelist);  

        Node root = nodelist.get(0);  

        System.out.println("递归先序遍历:");  

        tree.preOrderTraversal(root);  

        System.out.println();  

        System.out.println("非递归先序遍历:");  

        tree.preOrderTraversalbyLoop(root);  

        System.out.println();  

        System.out.println("递归中序遍历:");  

        tree.inOrderTraversal(root);  

        System.out.println();  

        System.out.println("非递归中序遍历:");  

        tree.inOrderTraversalbyLoop(root);  

        System.out.println();  

        System.out.println("递归后序遍历:");  

        tree.postOrderTraversal(root);  

        System.out.println();  

        System.out.println("非递归后序遍历:");  

        tree.postOrderTraversalbyLoop(root);  

        System.out.println();  

        System.out.println("广度优先遍历:");  

        tree.bfs(root);  

        System.out.println();  

        System.out.println("深度优先遍历:");  

        List<List<Integer>> rst = new ArrayList<>();  

        List<Integer> list = new ArrayList<>();  

        tree.dfs(root,rst,list);  

        System.out.println(rst);  

    }  

    /** 

     *  

     * @param datas 实现二叉树各节点值的数组 

     * @param nodelist 二叉树list 

     */  

    private void creatBinaryTree(int[] datas,List<Node> nodelist){  

        //将数组变成node节点  

        for(int nodeindex=0;nodeindex<datas.length;nodeindex++){  

            Node node = new Node(datas[nodeindex]);  

            nodelist.add(node);  

        }  

        //给所有父节点设定子节点  

        for(int index=0;index<nodelist.size()/2-1;index++){  

            //编号为n的节点他的左子节点编号为2*n 右子节点编号为2*n+1 但是因为list从0开始编号,所以还要+1  

            //这里父节点有1(2,3),2(4,5),3(6,7),4(8,9) 但是最后一个父节点有可能没有右子节点 需要单独处理  

            nodelist.get(index).setLeft(nodelist.get(index*2+1));   

            nodelist.get(index).setRight(nodelist.get(index*2+2));  

        }  

        //单独处理最后一个父节点  因为它有可能没有右子节点  

        int index = nodelist.size()/2-1;  

        nodelist.get(index).setLeft(nodelist.get(index*2+1)); //先设置左子节点  

        if(nodelist.size() % 2 == 1){ //如果有奇数个节点,最后一个父节点才有右子节点  

            nodelist.get(index).setRight(nodelist.get(index*2+2));  

        }  

    }  

    /** 

     * 遍历当前节点的值 

     * @param nodelist 

     * @param node 

     */  

    public void checkCurrentNode(Node node){  

        System.out.print(node.getVar()+" ");  

    }  

    /** 

     * 先序遍历二叉树 

     * @param root 二叉树根节点 

     */  

    public void preOrderTraversal(Node node){  

        if (node == null)  //很重要,必须加上 当遇到叶子节点用来停止向下遍历  

            return;    

        checkCurrentNode(node);  

        preOrderTraversal(node.getLeft());  

        preOrderTraversal(node.getRight());  

    }  

    /** 

     * 中序遍历二叉树 

     * @param root 根节点 

     */  

    public void inOrderTraversal(Node node){  

        if (node == null)  //很重要,必须加上  

            return;    

        inOrderTraversal(node.getLeft());  

        checkCurrentNode(node);  

        inOrderTraversal(node.getRight());  

    }  

    /** 

     * 后序遍历二叉树 

     * @param root 根节点 

     */  

    public void postOrderTraversal(Node node){  

        if (node == null)  //很重要,必须加上  

            return;    

        postOrderTraversal(node.getLeft());  

        postOrderTraversal(node.getRight());  

        checkCurrentNode(node);  

    }  

      

    /** 

     * 非递归前序遍历 

     * @param node 

     */  

    public void preOrderTraversalbyLoop(Node node){  

        Stack<Node> stack = new Stack();  

        Node p = node;  

        while(p!=null || !stack.isEmpty()){  

            while(p!=null){ //当p不为空时,就读取p的值,并不断更新p为其左子节点,即不断读取左子节点  

                checkCurrentNode(p);  

                stack.push(p); //将p入栈  

                p = p.getLeft();  

            }  

            if(!stack.isEmpty()){  

                p = stack.pop();  

                p = p.getRight();  

            }  

        }  

    }  

    /** 

     * 非递归中序遍历 

     * @param node 

     */  

    public void inOrderTraversalbyLoop(Node node){  

        Stack<Node> stack = new Stack();  

        Node p = node;  

        while(p!=null || !stack.isEmpty()){  

            while(p!=null){  

                stack.push(p);  

                p = p.getLeft();  

            }  

            if(!stack.isEmpty()){     

                p = stack.pop();  

                checkCurrentNode(p);  

                p = p.getRight();  

            }  

        }  

    }  

    /** 

     * 非递归后序遍历 

     * @param node 

     */  

    public void postOrderTraversalbyLoop(Node node){  

        Stack<Node> stack = new Stack<>();  

        Node p = node,prev = node;  

        while(p!=null || !stack.isEmpty()){  

            while(p!=null){  

                stack.push(p);  

                p = p.getLeft();  

            }  

            if(!stack.isEmpty()){  

                Node temp = stack.peek().getRight();  

                if(temp == null||temp == prev){  

                    p = stack.pop();  

                    checkCurrentNode(p);  

                    prev = p;  

                    p = null;  

                }else{  

                    p = temp;  

                }     

            }  

        }  

    }  

      

    /** 

     * 广度优先遍历(从上到下遍历二叉树) 

     * @param root 

     */  

    public void bfs(Node root){  

          if(root == null) return;  

          LinkedList<Node> queue = new LinkedList<Node>();  

          queue.offer(root); //首先将根节点存入队列  

          //当队列里有值时,每次取出队首的node打印,打印之后判断node是否有子节点,若有,则将子节点加入队列  

          while(queue.size() > 0){   

            Node node = queue.peek();  

            queue.poll(); //取出队首元素并打印  

            System.out.print(node.var+" ");  

            if(node.left != null){ //如果有左子节点,则将其存入队列  

              queue.offer(node.left);  

            }  

            if(node.right != null){ //如果有右子节点,则将其存入队列  

              queue.offer(node.right);  

            }  

          }  

    }  

    /** 

     * 深度优先遍历 

     * @param node 

     * @param rst 

     * @param list 

     */  

    public void dfs(Node node,List<List<Integer>> rst,List<Integer> list){  

        if(node == null) return;  

        if(node.left == null && node.right == null){  

            list.add(node.var);  

            /* 这里将list存入rst中时,不能直接将list存入,而是通过新建一个list来实现, 

             * 因为如果直接用list的话,后面remove的时候也会将其最后一个存的节点删掉*/  

            rst.add(new ArrayList<>(list));  

            list.remove(list.size()-1);  

        }  

        list.add(node.var);  

        dfs(node.left,rst,list);  

        dfs(node.right,rst,list);  

        list.remove(list.size()-1);  

    }  

    /** 

     * 节点类 

     * var 节点值 

     * left 节点左子节点 

     * right 右子节点 

     */   

    class Node{  

        int var;  

        Node left;  

        Node right;  

        public Node(int var){  

            this.var = var;  

            this.left = null;  

            this.right = null;  

        }  

        public void setLeft(Node left) {  

            this.left = left;  

        }  

        public void setRight(Node right) {  

            this.right = right;  

        }  

        public int getVar() {  

            return var;  

        }  

        public void setVar(int var) {  

            this.var = var;  

        }  

        public Node getLeft() {  

            return left;  

        }  

        public Node getRight() {  

            return right;  

        }  

          

    }  

  

}  

运行结果:

[java] view
plain copy

 





递归先序遍历:  

1 2 4 8 9 5 3 6 7   

非递归先序遍历:  

1 2 4 8 9 5 3 6 7   

递归中序遍历:  

8 4 9 2 5 1 6 3 7   

非递归中序遍历:  

8 4 9 2 5 1 6 3 7   

递归后序遍历:  

8 9 4 5 2 6 7 3 1   

非递归后序遍历:  

8 9 4 5 2 6 7 3 1   

广度优先遍历:  

1 2 3 4 5 6 7 8 9   

深度优先遍历:  

[[1, 2, 4, 8], [1, 2, 4, 9], [1, 2, 5], [1, 3, 6], [1, 3, 7]]  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: