java遞歸實現樹的一般操作

樹的操作

  • 創建樹
  • 銷燬樹
  • 前序遍歷樹
  • 中序遍歷樹
  • 後序遍歷樹
  • 層次遍歷樹
  • 求葉子節點[度爲0]個數
  • 求二叉樹第K層節點個數

求二叉樹第K層節點個數
在這裏插入圖片描述

遞歸代碼

// 需要一個數節點
public class TreeNode<T> {
    T value;
    TreeNode leftChild;
    TreeNode rightChild;

    public TreeNode() {
    }

    public TreeNode(T value) {
        this.value = value;
    }

    public void addLeftChild(T value) {
        TreeNode child = new TreeNode(value);
        this.leftChild = child;
    }



    public void addRightChild(T value) {
        TreeNode child = new TreeNode(value);
        this.rightChild = child;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        TreeNode<?> treeNode = (TreeNode<?>) o;
        return Objects.equals(value, treeNode.value) &&
                Objects.equals(leftChild, treeNode.leftChild) &&
                Objects.equals(rightChild, treeNode.rightChild);
    }

    @Override
    public int hashCode() {
        return Objects.hash(value, leftChild, rightChild);
    }
}
import java.util.LinkedList;
import java.util.Queue;

public class TreeTools {
    /*
     * 前序遍歷遞歸實現
     * */
    public static <T> void preOrderTravel(TreeNode<T> root) {
        if (root == null) {
            return;
        }

        System.out.print(root.value);
        System.out.printf("\t");
        preOrderTravel(root.leftChild);
        preOrderTravel(root.rightChild);
    }

    /**
     * 中序遍歷遞歸實現
     */
    public static <T> void midOrderTravel(TreeNode<T> root) {
        if (root == null) {
            return;
        }

        midOrderTravel(root.leftChild);
        System.out.print(root.value);
        System.out.printf("\t");
        midOrderTravel(root.rightChild);
    }

    /**
     * 後序遍歷遞歸實現
     */
    public static <T> void backOrderTravle(TreeNode<T> root) {
        if (root == null) {
            return;
        }

        backOrderTravle(root.leftChild);
        backOrderTravle(root.rightChild);
        System.out.print(root.value);
        System.out.printf("\t");
    }

    /*
     * 層次遍歷:使用隊列
     * */
    public static <T> void levelTravel(TreeNode<T> root) {
        Queue<TreeNode<T>> queue = new LinkedList<>();
        queue.offer(root);

        while (!queue.isEmpty()) {
            TreeNode<T> node = queue.poll();
            if (node.leftChild != null) {
                queue.offer(node.leftChild);
            }
            if (node.rightChild != null) {
                queue.offer(node.rightChild);
            }
            System.out.print(node.value);
            System.out.printf("\t");
        }
    }

    /**
     * getTreeDepth: 判斷樹的深度
     * 樹的深度  = Math.max(從左子樹數到當前節點的深度, 從右子樹數到當前節點的深度)
     *
     * @param root 根節點
     * @return int 返回類型
     */
    public static <T> int getTreeDepth(TreeNode<T> root) {
        if (root == null) {
            return 0;
        }

        int leftLength = getTreeDepth(root.leftChild) + 1;
        int rightDepth = getTreeDepth(root.rightChild) + 1;

        return Math.max(leftLength, rightDepth);
    }

    /**
     * getTreeNum: 判斷樹中節點個數
     * 思想: 樹節點個數 = 左邊樹節點個數 + 右邊樹節點個數 + 當前樹節點(1)
     *
     * @param root 根節點
     * @return int 返回類型
     */
    public static <T> int getTreeNum(TreeNode<T> root) {
        if (root == null) {
            return 0;
        }

        return getTreeNum(root.leftChild) + getTreeNum(root.rightChild) + 1;
    }

    /**
     * getNumForKlevel: 求第K層節點個數
     * 思路:第K層節點個數 = 第k層左子樹的節點個數 + 第k層右子樹的節點個數
     * ps:根節點爲第1層。 樹只有一個根節點
     *
     * @param root
     * @param k
     * @return int 返回類型
     */
    public static <T> int getNumForKlevel(TreeNode<T> root, int k) {
        if (root == null || k < 1) {
            return 0;
        }
        if (k == 1) {
            return 1;
        }
        int leftNum = getNumForKlevel(root.leftChild, k - 1);
        int rightNum = getNumForKlevel(root.rightChild, k - 1);
        return leftNum + rightNum;
    }

    /**
     * getLeafNum: 求二叉樹中葉子節點的個數
     * 葉子節點:沒有左孩子也沒有左孩子
     * 思路:二叉樹中葉子節點的個數  = 左葉子節點個數 + 又葉子節點個數
     *
     * @param root
     * @return int 返回類型
     */
    public static <T> int getLeafNum(TreeNode<T> root) {
        if (root == null) {
            return 0;
        }

        //如果二叉樹左子樹和右子樹皆爲空,說明該二叉樹根節點爲葉子節點,加1.
        if (root.leftChild == null && root.rightChild == null){
            return 1;
        }

        return getLeafNum(root.leftChild) + getLeafNum(root.rightChild);
    }

    /*
    * 交換二叉樹每個結點的左孩子和右孩子:
    * 
    * 一路走到左下角,然後交換左下角節點的爲止
    * 然後走回頭路
    * */
    public  static<T>  TreeNode<T> exchange(TreeNode<T> root){
        if (root == null){
            return null;
        }

        TreeNode<T> left = exchange(root.leftChild);
        TreeNode<T> right = exchange(root.rightChild);
        root.rightChild = left;
        root.leftChild = right;

        return root;
    }

    /**
     * nodeIsChild: 查看node是否是root的子節點
     * 思路:先序遍歷:現在左子樹裏面找,找得到就直接返回,找不到,就在右子樹裏面找
     * @param root
     * @param node
     * @return boolean 返回類型
     */
    public static <T> boolean nodeIsChild(TreeNode<T> root, TreeNode<T>node){
        if (root == null || node == null){
            return false;
        }

        if (root.equals(node)){
            return true;
        }

        boolean find = nodeIsChild(root.leftChild, node);
        if (!find){
            find = nodeIsChild(root.rightChild, node);
        }

        return find;
    }

    /**
     * findAllFatherNode: 返回兩個節點lnode和rnode的以root爲根節點的公共父節點
     *
     * @param root
     *            根節點
     * @param lNode
     * @param rNode
     * @return TreeNode 返回類型
     */

}
    public static void main(String[] args) {
        TreeNode<Integer> root = new TreeNode<>(1);
        root.addLeftChild(2);
        root.addRightChild(3);
        root.leftChild.addLeftChild(4);
        root.leftChild.addRightChild(6);
        root.leftChild.rightChild.addLeftChild(5);

        System.out.print("前序遍歷:\t");
        TreeTools.preOrderTravel(root);  //

        System.out.print("\n中序遍歷:\t");
        TreeTools.midOrderTravel(root);

        System.out.print("\n後序遍歷:\t");
        TreeTools.backOrderTravle(root);

        System.out.print("\n層次遍歷:\t");
        TreeTools.levelTravel(root);

        System.out.printf("\n遞歸樹的深度:\t%d", TreeTools.getTreeDepth(root));

        System.out.printf("\n樹的節點的個數:\t%d", TreeTools.getTreeNum(root));

        System.out.printf("\n第3層節點個數\t%d",   TreeTools.getNumForKlevel(root, 3));

        System.out.printf("\n葉子節點個數:\t%d",TreeTools.getLeafNum(root));

        TreeTools.exchange(root);
        System.out.print("前序遍歷:\t");
        TreeTools.preOrderTravel(root);  //

        System.out.printf("\nnode是root的子節點?\t%d", TreeTools.nodeIsChild(root, new TreeNode<>(33)) ? 1 : 0);
    }

創建隨機二叉樹

public class CreateTree {
    // 創建一個隨機二叉樹
    public static TreeNode CreateTree(TreeNode root, int value){
        if (root == null){
            return new TreeNode<>(value);
        }

        if (Math.random() > 0.5){
            if (root.leftChild == null){
                root.leftChild = new TreeNode<>(value);
            }else{
                root = CreateTree(root.leftChild, value);
            }
        }else{
            if (root.rightChild == null){
                root.rightChild = new TreeNode<>(value);
            }else{
                root = CreateTree(root.rightChild, value);
            }
        }

        return root;
    }

    public static void main(String[] args) {
        TreeNode<Integer> root = new TreeNode<>(11);
        for (int i = 0; i < 10; i++){
            CreateTree(root, i);
        }

        TreeTools.preOrderTravel(root);
        System.out.println();
        TreeTools.midOrderTravel(root);
        System.out.println();
        TreeTools.backOrderTravle(root);

        System.out.println(TreeTools.preNodeIsChild(root, new TreeNode<>(19)));
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章