二叉樹的層序遍歷

奮鬥的龍貓發表於2020-11-09

給你一個二叉樹,請你返回其按 層序遍歷 得到的節點值。 (即逐層地,從左到右訪問所有節點)。

來源:https://leetcode-cn.com/problems/binary-tree-level-order-traversal/
基本思路:這裡通過佇列實現迭代來實現的
1、定義一個佇列,用於存放節點
2、判斷佇列是否為空,如果不為空,那麼首先獲取當前佇列中的節點個數,然後再就從佇列中跳出一個節點,然後通過判斷這個節點左右子節點是否為null,從而可以知道是否要將它的左右子節點壓入佇列中,但是值得注意的是,必須要獲取當前佇列中的節點個數,從而可以知道每從佇列中跳出一個節點時,往集合中新增的節點之前有多少個節點
3、重複步驟2,直到佇列為空
節點類:

public class Node {
    public int value;
    public Node left;
    public Node right;
    public Node(int value){
        this.value = value;
    }

    @Override
    public String toString() {
        return value+" ";
    }
}

測試類:

/**
 * 二叉樹的層序遍歷(即從左到右進行輸出,並且逐層訪問
 * 基本思路:通過佇列實現迭代,從而實現二叉樹的層序遍歷
 * 1、將根節點壓入到佇列中
 * 2、之後,將從佇列中跳出一個節點,並且判斷這個新跳出節點的左右子節點是否為空,如果為空,就不要
 * 將其壓入到佇列中去,否則就將其壓入佇列中
 * 3、重複2操作,知道佇列為空
 */
public class TreeCenXuDisplay {
    public static List<List<Integer>> list = new ArrayList<>();
    public int[] arr = {4,5,8,10,12,15,18};//通過中序遍歷得到的陣列來構建二叉樹
    public static void main(String[] args) {
        TreeCenXuDisplay test = new TreeCenXuDisplay();
        Node root = test.buildTree(0,test.arr.length);
        System.out.print("通過中序遍歷得到的二叉樹的前序遍歷: ");
        test.display(root);
        System.out.println();
        System.out.println("二叉樹的層序遍歷: ");
        test.display2(root);
        for (List<Integer> list2: list) {
            System.out.println(list2);
        }
    }

    /**
     * 將一個按照升序排列的有序陣列(即二叉樹中序遍歷得到的),轉換為一棵高度平衡二叉搜尋樹。
     *本題中,一個高度平衡二叉樹是指一個二叉樹每個節點 的左右兩個子樹的高度差的絕對值不超過 1。
     * @param start
     * @param end
     */
    public Node buildTree(int start, int end) {
        if(start >= end){
            /**
             * 如果範圍不正確的時候,結束遞迴,注意這裡必須要有=,因為end一開始傳遞的引數時陣列的長度,此時
             * end - start表示的是陣列的長度,此時如果start = end是,表示的是有0個元素,所以結束遞迴,
             * start > end就更不用說了
             */
            return null;
        }
        int mid = (start + end) / 2;//陣列中間或者中間偏一個節點是根節點
        Node root = new Node(arr[mid]);//新建一個根節點
        //構建左子樹、右子樹
        root.left = buildTree(start,mid);
        root.right = buildTree(mid + 1,end);
        return root;
    }

    /**
     * 樹的前序遍歷
     */
    public void display(Node root) {
          if(root == null){
              return;
          }
          System.out.print(root + " ");
          display(root.left);
          display(root.right);
    }

    /**
     * 樹的層序遍歷:通過一個佇列實現迭代,從而實現層序遍歷
     * 基本思路:
     * 1、定義一個佇列,用於存放節點
     * 2、判斷佇列是否為空,如果不為空,那麼首先獲取當前佇列中的節點個數,然後再就從佇列中跳出一個節點,然後通過判斷這個
     * 節點左右子節點是否為null,從而可以知道是否要將它的左右子節點壓入佇列中,但是值得注意的是,必須要獲取當前佇列中的節點個數,從而可以知道每從佇列中跳出一個節點時,往集合中新增的節點有多少個
     * 3、重複步驟2,知道佇列為空
     */
    public void display2(Node root){
        //定義一個佇列
        Queue<Node> queue = new LinkedList<>();
        //定義一個集合
        ArrayList<Integer> arrayList = null;
        //將根節點新增到佇列中
        queue.offer(root);
        //通過判斷佇列是否為空,從而將其左右子節點新增到佇列中
        while(!queue.isEmpty()){
            arrayList = new ArrayList<>();
            //獲取當前佇列中的節點個數
            int size = queue.size();
            for (int i = 0; i < size; i++) {
                //注意的是,這裡的迴圈條件不可以時queue.size,否則就會發生報錯
                //將佇列中跳出一個根節點,並將其對應的值新增到集合arrayList中
                root = queue.poll();
                arrayList.add(root.value);
                //判斷當前根節點的左右子節點是否為空,如果不為空,就新增到佇列中
                if(root.left != null){
                    queue.offer(root.left);
                }
                if(root.right != null){
                    queue.offer(root.right);
                }
            }
            list.add(arrayList);//將一個集合新增到list中
        }
    }
}

運算結果:
在這裡插入圖片描述
值得注意的是,構造層序遍歷的程式碼不可以是這樣子的,即不可以是單層迴圈:

/**
     * 這裡沒有直到每一層中的節點個數,並且只是單層迴圈,那麼每一次只能向佇列中新增兩個節點
     * 所以需要有巢狀迴圈,並且第二層迴圈的迴圈條件是要直到每一層中節點個數,即佇列的節點個數
     * @param root
     */
    private void display3(Node root) {
        //新建一個佇列
        Queue<Node> queue = new LinkedList<>();
        //新建一個集合
        ArrayList<Integer> arrayList = new ArrayList<>();
        //將根節點壓入到對了中
        queue.offer(root);
        arrayList.add(root.value);
        list.add(arrayList);
        while(!queue.isEmpty()){
            arrayList = new ArrayList<>();
            root = queue.poll();//從佇列中跳出根節點
            //判斷它的左右子節點是否為空,如果不為空,就新增到佇列中
            if(root.left != null){
                queue.offer(root.left);
                arrayList.add(root.left.value);
            }
            if(root.right != null){
                queue.offer(root.right);
                arrayList.add(root.right.value);
            }
            list.add(arrayList);
        }
    }

否則對應的錯誤結果是這樣的:
在這裡插入圖片描述
也正如此,所以需要通過迴圈巢狀實現二叉樹的層序遍歷,並且需要直到每一層的節點個數

相關文章