二叉樹的DFS (深度優先遍歷)算法 Java 實現

深度優先遍歷簡介和實現

深度優先遍歷(Depth First Search)簡介:

先從根節點沿着(左或者右)分支走到底,當再也沒有葉子節點之後,返回上一節點,如果上一個節點還有另外一個子節點,那麼遍歷這個節點分支直至再也沒有葉子節點,之後重複上面的過程

在這裏插入圖片描述
例如上圖按照先遍歷左分支再遍歷右分支的深度優先遍歷順序就是:
A B D E C F G

不難發現其實就是前序遍歷

實現:

深度優先遍歷的實現方式一般分爲遞歸式和非遞歸式

遞歸式:

遞歸實現比較簡單,由於是前序遍歷,所以我們依次遍歷當前節點,左節點,右節點即可,對於左右節點來說,依次遍歷它們的左右節點即可,依此不斷遞歸下去,直到葉節點(遞歸終止條件),代碼如下

package search;

import java.util.Stack;

/**
 * @author huchenfei
 * @version 1.0
 * @className DeepFirstSearch
 * @description 二叉樹深度遍歷算法
 * @date 2020/6/2 15:38
 **/
public class DepthFirstSearch {

    private static class Node {
        /**
         * 節點值
         */
        public int value;
        /**
         * 左節點
         */
        public Node left;
        /**
         * 右節點
         */
        public Node right;

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

    }

    public static void main(String... args) {
        Node head = new Node(1);
        Node second = new Node(2);
        Node three = new Node(3);
        Node four = new Node(4);
        Node five = new Node(5);
        Node six = new Node(6);
        Node seven = new Node(7);

        head.right = three;
        head.left = second;
        second.right = five;
        second.left = four;
        three.right = seven;
        three.left = six;
        System.out.println("遞歸方式 -> 深度優先遍歷結果: ");
        recursiveDfs(head);
        System.out.println();
    }

    /**
     * 遞歸方式實現 DFS
     *
     * @param head 二叉樹
     */
    public static void recursiveDfs(Node head) {
        if (head == null) {
            return;
        }
        System.out.print(head.value);
        System.out.print(" ");
        // 遍歷左節點
        recursiveDfs(head.left);
        // 遍歷右節點
        recursiveDfs(head.right);
    }
}

遞歸的表達性很好,也很容易理解,不過如果層級過深,很容易導致棧溢出。所以我們重點看下非遞歸實現

非遞歸式:

仔細觀察深度優先遍歷的特點,對二叉樹來說,由於是先序遍歷(先遍歷當前節點,再遍歷左節點,再遍歷右節點),所以我們有如下思路

  1. 對於每個節點來說,先遍歷當前節點,然後把右節點壓棧,再壓左節點(這樣彈棧的時候會先拿到左節點遍歷,符合深度優先遍歷要求)
  2. 彈棧,拿到棧頂的節點,如果節點不爲空,重複步驟 1, 如果爲空,結束遍歷。
package search;

import java.util.Stack;

/**
 * @author huchenfei
 * @version 1.0
 * @className DeepFirstSearch
 * @description 二叉樹深度遍歷算法
 * @date 2020/6/2 15:38
 **/
public class DepthFirstSearch {

    private static class Node {
        /**
         * 節點值
         */
        public int value;
        /**
         * 左節點
         */
        public Node left;
        /**
         * 右節點
         */
        public Node right;

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

    }

    public static void main(String... args) {
        Node head = new Node(1);
        Node second = new Node(2);
        Node three = new Node(3);
        Node four = new Node(4);
        Node five = new Node(5);
        Node six = new Node(6);
        Node seven = new Node(7);

        head.right = three;
        head.left = second;
        second.right = five;
        second.left = four;
        three.right = seven;
        three.left = six;
        System.out.println("非遞歸方式 -> 深度優先遍歷結果: ");
        unRecursiveDfs(head);
        System.out.println();
    }

    /**
     * 非遞歸的使用棧來實現 DFS
     * 依據棧的先進後出特性
     * 1. 將二叉樹的頭結點放入棧中
     * 2. 將頭結點 1 從棧中彈出,並查看頭結點是否有左右節點,將右節點和左節點壓入棧中【3,2】
     * 3. 將頭結點 2 從棧中彈出,並查看 2 節點是否有左右節點,將右節點和左節點壓入棧中【3,5,4】
     * 4. 將頭結點 4 從棧中彈出,無左右節點【3,5】
     * 5. 將頭結點 5 從棧中彈出,無左右節點【3】
     * 6. 將頭結點 3 從棧中彈出,並查看 3 節點是否有左右節點,將右節點和左節點壓入棧中【7,6】
     * 7. 將頭結點 6 從棧中彈出,無左右節點【7】
     * 8. 將頭結點 7 從棧中彈出,無左右節點
     *
     * @param head 二叉樹
     */
    public static void unRecursiveDfs(Node head) {
        if (head == null) {
            return;
        }

        Stack<Node> stack = new Stack<>();
        // 先將根結點壓入棧中
        stack.push(head);
        while (!stack.isEmpty()) {
            Node node = stack.pop();
            System.out.print(node.value);
            System.out.print(" ");

            // 將節點右邊的壓入棧中
            if (node.right != null) {
                stack.push(node.right);
            }

            // 壓入左邊的棧中
            if (node.left != null) {
                stack.push(node.left);
            }
        }
    }
}

拓展:

二叉樹的 BFS (廣度優先遍歷)算法 Java 實現


參考:

二叉樹的廣度優先遍歷和深度優先遍歷(Java實現)
圖文詳解 DFS 算法 和 BFS 算法
二叉樹的深度優先搜索和廣度優先搜索(java實現)

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