判斷二叉樹是否為滿二叉樹

Grey Zeng發表於2022-12-03

判斷二叉樹是否為滿二叉樹

作者:Grey

原文地址:

部落格園:判斷二叉樹是否為滿二叉樹

CSDN:判斷二叉樹是否為滿二叉樹

滿二叉樹定義

一個二叉樹,如果每一個層的結點數都達到最大值,則這個二叉樹就是滿二叉樹。也就是說,如果一個二叉樹的層數為K,且結點總數是(2^k) -1 ,則它就是滿二叉樹。

方法1

使用公式,求二叉樹的層數 k, 結點數 n,如果滿足(2^k) -1 = n,則為滿二叉樹。

定義資料結構

    public static class Info1 {
        public int height;
        public int nodes;

        public Info1(int h, int n) {
            height = h;
            nodes = n;
        }
    }

其中height表示二叉樹的層數,nodes表示二叉樹的結點個數。

定義遞迴函式

Info1 process1(Node head)

遞迴含義是:head 為頭的二叉樹的層數和點數都是多少,接下來就是 base case

即:head == null的時候,此時,height == 0nodes == 0

        if (head == null) {
            return new Info1(0, 0);
        }

接下來是普遍情況

// 去左樹上收集資訊
Info1 leftInfo = process1(head.left);
// 去右樹上收集資訊
Info1 rightInfo = process1(head.right);
// 整合成 head 自己的資訊
int height = Math.max(leftInfo.height, rightInfo.height) + 1;
int nodes = leftInfo.nodes + rightInfo.nodes + 1;
return new Info1(height, nodes);

方法2

定義如下資料結構

    public static class Info2 {
        public boolean isFull;
        public int height;

        public Info2(boolean f, int h) {
            isFull = f;
            height = h;
        }
    }

其中isFull表示是否為滿二叉樹,height表示二叉樹的高度。

定義了這個資料結構後,可以梳理可能性,如果以 head 為頭的樹要符合滿二叉樹。則需要同時滿足下面三種情況

情況1:左樹是滿二叉樹

情況2:右樹是滿二叉樹;

情況3:左右樹的高度一樣。

定義遞迴函式

Info2 process2(Node head)

遞迴含義就是返回以head為頭的二叉樹Info2結構資訊。

base case是

        if (h == null) {
            return new Info2(true, 0);
        }

h == null預設是滿二叉樹,結點個數為0。

接下來是普遍情況,即去左右子樹收集相關資訊,整合成以h為頭二叉樹的資訊。

    // 去左子樹收集相關資訊
    Info2 leftInfo = process2(h.left);
    // 去右子樹收集相關資訊
    Info2 rightInfo = process2(h.right);
    // 整合成 h 自己的新
    boolean isFull = leftInfo.isFull && rightInfo.isFull && leftInfo.height == rightInfo.height;
    int height = Math.max(leftInfo.height, rightInfo.height) + 1;
    return new Info2(isFull, height);

方法1 和 方法2 的時間複雜度都是O(n),即經過一次後序遍歷的時間複雜度。

兩種解法的完整程式碼(含測試程式碼)如下

public class Code_IsFull {
    public static class Node {
        public int value;
        public Node left;
        public Node right;

        public Node(int data) {
            this.value = data;
        }
    }

    // 第一種方法
    // 收集整棵樹的高度h,和節點數n
    // 只有滿二叉樹滿足 : 2 ^ h - 1 == n
    public static boolean isFull1(Node head) {
        if (head == null) {
            return true;
        }
        Info1 all = process1(head);
        return (1 << all.height) - 1 == all.nodes;
    }

    public static class Info1 {
        public int height;
        public int nodes;

        public Info1(int h, int n) {
            height = h;
            nodes = n;
        }
    }

    public static Info1 process1(Node head) {
        if (head == null) {
            return new Info1(0, 0);
        }
        Info1 leftInfo = process1(head.left);
        Info1 rightInfo = process1(head.right);
        int height = Math.max(leftInfo.height, rightInfo.height) + 1;
        int nodes = leftInfo.nodes + rightInfo.nodes + 1;
        return new Info1(height, nodes);
    }

    // 第二種方法
    // 收集子樹是否是滿二叉樹
    // 收集子樹的高度
    // 左樹滿 && 右樹滿 && 左右樹高度一樣 -> 整棵樹是滿的
    public static boolean isFull2(Node head) {
        if (head == null) {
            return true;
        }
        return process2(head).isFull;
    }

    public static class Info2 {
        public boolean isFull;
        public int height;

        public Info2(boolean f, int h) {
            isFull = f;
            height = h;
        }
    }

    public static Info2 process2(Node h) {
        if (h == null) {
            return new Info2(true, 0);
        }
        Info2 leftInfo = process2(h.left);
        Info2 rightInfo = process2(h.right);
        boolean isFull = leftInfo.isFull && rightInfo.isFull && leftInfo.height == rightInfo.height;
        int height = Math.max(leftInfo.height, rightInfo.height) + 1;
        return new Info2(isFull, height);
    }

    // for test
    public static Node generateRandomBST(int maxLevel, int maxValue) {
        return generate(1, maxLevel, maxValue);
    }

    // for test
    public static Node generate(int level, int maxLevel, int maxValue) {
        if (level > maxLevel || Math.random() < 0.5) {
            return null;
        }
        Node head = new Node((int) (Math.random() * maxValue));
        head.left = generate(level + 1, maxLevel, maxValue);
        head.right = generate(level + 1, maxLevel, maxValue);
        return head;
    }

    public static void main(String[] args) {
        int maxLevel = 5;
        int maxValue = 100;
        int testTimes = 1000000;
        System.out.println("測試開始");
        for (int i = 0; i < testTimes; i++) {
            Node head = generateRandomBST(maxLevel, maxValue);
            if (isFull1(head) != isFull2(head)) {
                System.out.println("出錯了!");
            }
        }
        System.out.println("測試結束");
    }
}

更多

演算法和資料結構筆記

相關文章