Java–二叉树–链式存储

篇1:Java–顺序表:
篇2:Java–单链表:


方法接口

package pers.xu.ds2.btree;

/**二叉树接口
 * 方便使用不同的存储结构实现,比如顺序结构,链式结构
 * @author a_apple
 * @create 2019-11-15 17:01
 */
public interface BinaryTree {

    /**
     * 是否空树
     */
    public boolean isEmpty();

    /**
     * 树节点数量
     */
    public int size();

    /**
     * 获取树的高度
     */
    public int getHeight();

    /**
     * 查询指定值的节点
     */
    public Node findKey(int value);

    /**
     * 前序遍历
     */
    public void preOrderTraverse();

    /**
     * 中序遍历
     */
    public void inOrderTraverse();

    /**
     * 后序遍历递归操作
     */
    public void postOrderTraverse();

    /**
     * 后序遍历递归操作
     * @param node 树根节点
     */
    public void postOrderTraverse(Node node);

    /**
     * 中序遍历非递归操作
     * 1)对于任意节点current,若该节点不为空则将该节点压栈,并将左子树节点置为current,重复此操作,直到
     * 2)若左子树为空,栈顶节点出栈,访问节点后将该节点的右子树置为current
     * 3)重复1、2步操作,直到current为空且栈内节点为空。
     */
    public void inOrderByStack();

    /**
     * 前序遍历非递归操作
     * 1)对于任意节点current,若该节点不为空则访问该节点后再将节点压栈,并将左子树节点置为current,重
     * 2)若左子树为空,栈顶节点出栈,将该节点的右子树置为current
     * 3)重复1、2步操作,直到current为空且栈内节点为空。
     */
    public void preOrderByStack();

    /**
     * 后序遍历非递归操作
     * 1)对于任意节点current,若该节点不为空则访问该节点后再将节点压栈,并将左子树节点置为current,重复
     * 2)若左子树为空,取栈顶节点的右子树,如果右子树为空或右子树刚访问过,则访问该节点,并将preNode置为该干
     * 3)重复1、2步操作,直到current为空且栈内节点为空。
     */
    public void postOrderByStack();

    /**
     * 借助队列实现层次遍历
     */
    public void levelOrderByQueue();
}

树节点

package pers.xu.ds2.btree;

/**二叉树节点
 * @author a_apple
 * @create 2019-11-15 16:53
 */
public class Node {

    Object value;
    Node left;
    Node right;

    public Node(Object value, Node left, Node right) {
        this.value = value;
        this.left = left;
        this.right = right;
    }

    @Override
    public String toString() {
        return "Node{" +
                "data=" + value +
                ", left=" + left +
                ", right=" + right +
                '}';
    }
}

二叉树类

package pers.xu.ds2.btree;

import java.util.Deque;
import java.util.LinkedList;
import java.util.Queue;

/**
 * @author a_apple
 * @create 2019-11-15 17:15
 */
public class LinkedBinaryTree implements BinaryTree {

    private Node root;

    public LinkedBinaryTree(Node root) {
        this.root = root;
    }

    @Override
    public boolean isEmpty() {
        return root == null;
    }

    @Override
    public int size() {
        System.out.print("节点个数:");
        return this.size(root);
    }

    private int size(Node node){
        if(node == null){
            return 0;
        }else {
            //左子树高度
            int lh = this.size(node.left);
            //右子树高度
            int rh = this.size(node.right);
            //1 : 代表的是当前节点node
            return lh+rh+1;
        }
    }

    @Override
    public int getHeight() {
        System.out.print("高度:");
        return this.getHeight(root);
    }
    private int getHeight(Node node) {
        if(node == null){
            return 0;
        }else {
            //左子树高度
            int lh = getHeight(node.left);
            //右子树高度
            int rh = getHeight(node.right);
            return lh>rh?lh+1:rh+1;
        }
    }

    @Override
    public Node findKey(int value) {
        return this.findKey(value,root);
    }

    private Node findKey(Object value,Node root){
        if(root == null){
            return null;
        }else if(root.value == value){
            return root;
        }else {
            Node node1 = this.findKey(value,root.left);
            Node node2 = this.findKey(value,root.right);
            if(node1 != null && node1.value == value){
               return node1;
            }else if(node2 != null && node2.value == value){
                return node2;
            }else {
                return null;
            }
        }
    }

    @Override
    public void preOrderTraverse() {
        System.out.println("前序遍历:");
        preOrderTraverse(root);
        System.out.println();
    }

    private void preOrderTraverse(Node node) {
        if(node != null){
        //先输出根节点
            System.out.print(node.value+"  ");
        //然后递归左子树
            preOrderTraverse(node.left);
        //递归右子树
            preOrderTraverse(node.right);
        }
    }

    @Override
    public void inOrderTraverse() {
        System.out.println("中序遍历:");
        inOrderTraverse(root);
        System.out.println();
    }
    private void inOrderTraverse(Node node) {
        if(node != null){
            //遍历左
            inOrderTraverse(node.left);
            //输出根
            System.out.print(node.value+"  ");
            //右子树
            inOrderTraverse(node.right);
        }
    }

    @Override
    public void postOrderTraverse() {
        System.out.println("后序遍历:");
        postOrderTraverse(root);
        System.out.println();
    }

    @Override
    public void postOrderTraverse(Node node) {
        if(node != null){
            //遍历左
            postOrderTraverse(node.left);
            //遍历右
            postOrderTraverse(node.right);
            //输出根
            System.out.print(node.value+"  ");
        }
    }

    @Override
    public void inOrderByStack() {
        System.out.println("非递归中序遍历:");

            //创建栈
            Deque<Node> stack = new LinkedList<>();
            Node current = root;
            while (current != null || !stack.isEmpty()){
                while (current != null){
                    stack.push(current);
                    current = current.left;
                }

            if(!stack.isEmpty()){
                current = stack.pop();
                System.out.print(current.value+"  ");
                current = current.right;
            }
        }

        System.out.println();
    }

    @Override
    public void preOrderByStack() {
        System.out.println("非递归前序遍历:");
        this.preOrderByStack(root);
        System.out.println();
    }

    private void preOrderByStack(Node node){
        Deque<Node> stack = new LinkedList<>();
        Node p = node;
        while(!stack.isEmpty() || p != null){
            if(p != null){
                stack.push(p);
                System.out.print(p.value+"  ");
                p = p.left;
            }else {
                p = stack.pop();
                p = p.right;
            }
        }
    }

    @Override
    public void postOrderByStack() {
        System.out.println("非递归后序遍历:");
        this.postOrderByStack(root);
        System.out.println();
    }

    /**
     * 双栈法
     * @param node
     */
    private void postOrderByStack(Node node) {
        Deque<Node> s = new LinkedList<>(), s2 = new LinkedList<>();
        Node p;
        s.push(node);
        while (!s.isEmpty()) {
            p = s.pop();
            s2.push(p);
            if (p.left != null) {
                //这里是先左再右  (非递归前序是先右再左)
                s.push(p.left);
            }
            if (p.right != null) {
                s.push(p.right);
            }
        }
        while (!s2.isEmpty()) {
            System.out.print(s2.pop().value + "  ");
        }
    }

    @Override
    public void levelOrderByQueue() {
        System.out.println("层次遍历:");

        if(root == null) {
            return;
        }
        Queue<Node> queue = new LinkedList<>();
        //根节点入队---第一层
        queue.add(root);

        //对整个队列判空  -->直到最后一层节点出队
        while (queue.size() != 0){
            //按层次出队,输出       len:每层元素的个数
            int len = queue.size();
            //一层层出队,一层层进队
            for (int i = 0; i < len; i++) {
                Node temp = queue.poll();
                assert temp != null;
                System.out.print(temp.value+" ");

                //父节点出队后,再将孩子添加到队列里(构成下一层节点)
                if(temp.left != null){
                    queue.add(temp.left);
                }
                if(temp.right != null){
                    queue.add(temp.right);
                }
            }
            System.out.print("  ");
        }
        System.out.println();
    }
}

测试类

package pers.xu.ds2.btree;

/**
 * @author a_apple
 * @create 2019-11-15 17:16
 */
public class Test {

    public static void main(String[] args) {
        //前序创建:根-左-右 1 4 5 2 3 6 7
        //1.创建二叉树
        Node node7 = new Node(7,null,null);
        Node node3 = new Node(3,null,null);
        Node node6 = new Node(6,null,node7);
        Node node2 = new Node(2,node3,node6);
        Node node5 = new Node(5,null,null);
        Node node4 = new Node(4,null,node5);
        Node node1 = new Node(1,node4,node2);

        LinkedBinaryTree btree = new LinkedBinaryTree(node1);

        //2.判断树空
        boolean empty = btree.isEmpty();
        System.out.println("isEmpty:"+empty);
        //3.前序  1452367
        btree.preOrderTraverse();
        //4.中序  4513267
        btree.inOrderTraverse();
        //5.后序  5437621
        btree.postOrderTraverse();

        System.out.println("-------------------------非递归遍历");

        //3.前序,非递归
        btree.preOrderByStack();
        //4.中序,非递归
        btree.inOrderByStack();
        //5.后序,非递归
        btree.postOrderByStack();

        System.out.println("-------------------------");

        // .层次遍历 1 42 536 7
        btree.levelOrderByQueue();

        //7.高度
        System.out.println(btree.getHeight());

        //8.节点个数
        System.out.println(btree.size());

        //9.查找节点
        System.out.println(btree.findKey(6));
     }
}

输出结果:

isEmpty:false
前序遍历:
1  4  5  2  3  6  7  
中序遍历:
4  5  1  3  2  6  7  
后序遍历:
5  4  3  7  6  2  1  
-------------------------非递归遍历
非递归前序遍历:
1  4  5  2  3  6  7  
非递归中序遍历:
4  5  1  3  2  6  7  
非递归后序遍历:
5  4  3  7  6  2  1  
-------------------------
层次遍历:
1   4 2   5 3 6   7   
高度:4
节点个数:7
Node{data=6, left=null, right=Node{data=7, left=null, right=null}}