由不完全數組構造非完全(任意)二叉樹

構造二叉樹&4種遍歷方法

        目的:通過一個任意數組(可以包含Null,而且空的節點沒必要全部用Null值填充)來構造一個任意形式的二叉樹(可以是完全二叉樹,也可以是非完全二叉樹)。

        看網上好多教程由數組構造二叉樹都是“完全二叉樹”,即使可以產生非完全二叉樹也必須將空節點全部用Null表示填入數組中(這樣其實就跟完全二叉樹等效了)。這裏用Python2和Java兩種語言實現了通過任意數組構造任意二叉樹。

        這樣便可以模仿leetcode平臺在自己的IDE中進行關於二叉樹題目的debug了。

        另外,實現四種遍歷方式(前序、中序、後序遍歷,以及層次遍歷),以print構造的二叉樹。

1. Python2實現

    # 創建二叉樹。 從含有None的數組創建非完全二叉樹 !!!
    # 將list換成隊列queue,pop(0)更方便。
    def creatTree(self, nums):
        if not nums:
            return None
        root = TreeNode(nums[0])
        nums.remove(nums[0])
        lst = [root]
        while(lst and nums):
            tmp = lst[0]
            lst.remove(lst[0])
            if tmp:
                left = nums[0]
                tmp.left = TreeNode(left) if left else None
                nums.remove(nums[0])
                lst.append(tmp.left)
                try:
                    right = nums[0]
                    tmp.right = TreeNode(right) if right else None
                    nums.remove(nums[0])
                    lst.append(tmp.right)
                except:
                    pass
        return root

這裏其實使用queue更方便,從尾部push頭部pop。

下邊Python的遍歷只寫兩種,前序和層次。

    # 先序遍歷
    def preorder(self, root):
        """遞歸實現先序遍歷"""
        if root == None:
            return
        print(root.val),
        self.preorder(root.left)
        self.preorder(root.right)

    # 層次遍歷
    def levelOrder(self, root):
        if not root:
            return None
        queue = list()
        # queue = []
        queue.append(root)
        while(queue):
            node = queue.pop(0)
            print node.val,
            if node.left:
                queue.append(node.left)
            if node.right:
                queue.append(node.right)

2. Java實現

package leetcode.easy;

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

class TreeNode {
     int val;
     TreeNode left;
     TreeNode right;
     TreeNode(int x) { val = x; }
}


public class CreatBinaryTree {
    // 遞歸法構建完全二叉樹,不是完全二叉樹的話葉構建不出來。
    public static TreeNode createCompleteBT(Integer[] arr, int i) // 初始時,傳入的i==0
    {
        TreeNode root = null; // 定義根節點

        if (i >= arr.length) // i >= arr.length 時,表示已經到達了根節點
            return null;
        // System.out.println(arr[i]);
        if (arr[i] == null) {  // 是null的話直接return,否則下面TreeNode(arr[i])會error。
            return null;
        }

        root = new TreeNode(arr[i]); // 根節點
        root.left = createCompleteBT(arr, 2*i+1); // 遞歸建立左孩子結點
        root.right = createCompleteBT(arr, 2*i+2); // 遞歸建立右孩子結點

        return root;
    }

    // 創建二叉樹,從含有None的數組創建非完全二叉樹 !!!
    // 將list換成隊列queue,pop(0)更方便。
    public static TreeNode creatAnyBiTreeByArr(Integer[] arr){
        Queue<Integer> queue_num = new LinkedList<Integer>();
        for(int i=0;i<arr.length;i++){
            queue_num.add(arr[i]);
            // ((LinkedList<Integer>) q1).add(null);
        }
        if (queue_num.isEmpty()) return null;
        TreeNode root = new TreeNode(queue_num.poll());  // poll() 方法在用空集合調用時不是拋出異常,只是返回 null !!
        Queue<TreeNode> que_node = new LinkedList<TreeNode>();
        que_node.offer(root);

        while (!que_node.isEmpty() && !queue_num.isEmpty()){
            TreeNode tmp = que_node.poll();
            if(tmp != null){
                Integer left = queue_num.poll();
                Integer right = queue_num.poll();
                if(left != null)
                    tmp.left = new TreeNode(left);
                else tmp.left = null;
                que_node.offer(tmp.left);

                if(right != null)
                    tmp.right = new TreeNode(right);
                else tmp.right = null;
                que_node.offer(tmp.right);
            }
        }
        return root;
    }

    // 先序遍歷
    public static void preOrder(TreeNode root)
    {
        if (root == null)
            return;
        System.out.print(root.val+" ");
        preOrder(root.left);
        preOrder(root.right);
    }

    // 中序遍歷
    public static void inOrder(TreeNode root)
    {
        if (root == null)
            return;
        inOrder(root.left);
        System.out.print(root.val+" ");
        inOrder(root.right);
    }

    // 後序遍歷
    public static void postOrder(TreeNode root)
    {
        if (root == null)
            return;
        postOrder(root.left);
        postOrder(root.right);
        System.out.print(root.val+" ");
    }

    // 層次遍歷
    public static void levelOrder(TreeNode root)
    {
        if (root == null){
            return;
        }
        //add()和remove()方法在失敗的時候會拋出異常(不推薦)
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        queue.offer(root);
        while (! queue.isEmpty()) {
            TreeNode node = queue.poll();
            System.out.print(node.val+" ");
            if (node.left != null){
                queue.offer(node.left);
            }
            if (node.right != null){
                queue.offer(node.right);
            }
        }
    }

    // ########## test ##########
    public static void main(String[] args) {
        CreatBinaryTree sl = new CreatBinaryTree();

        //  ***************  ...
        Integer[] data1 = new Integer[] {0,1,2,null,3,4,null,5};
        Integer[] data3 = new Integer[] {0,1,null,2,null,3};
        TreeNode root1 = createCompleteBT(data1,0);
        TreeNode root2 = creatAnyBiTreeByArr(data1);

        // 構建任意二叉樹
        TreeNode root3 = sl.creatAnyBiTreeByArr(data3);

        levelOrder(root1);  // 0 1 2 3 4
        System.out.println();

        preOrder(root1);  // 0 1 3 2 4
        System.out.println();
        preOrder(root2); // 0 1 3 5 2 4 
        System.out.println();

        sl.levelOrder(root3);  // 0 1 2 3
        System.out.println();
        sl.preOrder(root3);  // 0 1 2 3
    }
}

對比root1和root2的結果,同樣的數組,不同的樹結構,因爲前者只能構造“完全二叉樹”或者由Null值填充空位的僞完全二叉樹(如將data1填充成爲[0,1,2,null,3,4,null,null,null,5], 便可以通過createCompleteBT 函數構造與後者creatAnyBiTreeByArr相同的形式了)。

3. 樹結構可視化

如數組[0, 1, null, 2, null, 3] 通過creatAnyBiTreeByArr函數構造出來的數的形式如下圖,這裏不需要把此數組填充成爲[0, 1, null, 2, null, null, null, 3].

 

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