多級樹的深度優先遍歷與廣度優先遍歷(Java實現)


多級樹的深度優先遍歷與廣度優先遍歷(Java實現)

深度優先遍歷與廣度優先遍歷其實是屬於圖算法的一種,多級樹可以看做是一種特殊的圖,所以多級數的深/廣遍歷直接套用圖結構的遍歷方法即可。

工程中后端通常會用多級樹來存儲頁面表單的各級聯動類目,本文提供了深度遍歷與廣度遍歷的示例,在使用時只要根據你的業務需求稍加改動即可。

我們知道,遍歷有遞歸,非遞歸兩種方式。在工程項目上,一般是禁用遞歸方式的,因為遞歸非常容易使得系統爆棧。同時,JVM也限制了最大遞歸數量,在你的樹結構非常深的時候很容易出現StackOverflowError異常,所以最好采用非遞歸的方式。

節點模型

public class Node {
    //值
    public int value;
    //所有的子節點
    public ArrayList<Node> nexts;

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

深度優先遍歷

深度優先搜索英文縮寫為DFS即Depth First Search.其過程簡要來說是對每一個可能的分支路徑深入到不能再深入為止,而且每個節點只能訪問一次。多級樹可以看做一個特殊的圖結構,總的來說遍歷的方法還是不變的,都是利用棧和Set來進行操作。

主要步驟:

  1. 准備一個棧結構和一個Set結構的集合,棧用來記錄還有孩子沒有被遍歷到的節點,Set用來記錄遍歷的歷史記錄
  2. 將首節點加入到棧和set中
  3. 彈棧拿到首節點
  4. 從首節點開始深度遍歷,下面示例代碼配合注解近進行理解。
public static void dfs(Node node) {
    if (node == null) {
        return;
    }
    Stack<Node> stack = new Stack<>();
    HashSet<Node> set = new HashSet<>();
    stack.add(node);
    set.add(node);
    System.out.println(node.value);
    
    while (!stack.isEmpty()) {
        //彈棧獲得一個節點
        Node cur = stack.pop();
        //查看這個節點的所有孩子
        for (Node next : cur.nexts) {
            //如果有孩子是之前沒有遍歷到的,說明這個節點沒有深度遍歷完
            if (!set.contains(next)) {
                //此節點與其孩子加入棧與Set中
                stack.push(cur);
                stack.push(next);
                set.add(next);
                System.out.println(next.value);
                break;
            }
        }
    }
}

廣度優先遍歷

寬度優先搜索算法(又稱廣度優先搜索)是最簡便的圖的搜索算法之一,這一算法也是很多重要的圖的算法的原型。對於多級數來說,就是先遍歷該節點的所有孩子,然后在遍歷孩子節點的所有孩子,先遍歷一層再遍歷下一次層。

主要思路就是利用隊列來將下一層的所有節點記錄下來,然后順序遍歷就可以了。

public static void bfs(Node node) {
    if (node == null) {
        return;
    }
    Queue<Node> queue = new LinkedList<>();
    //用來注冊已加入隊列的節點——>防止重復添加節點
    HashSet<Node> set = new HashSet<>();
    queue.add(node);
    set.add(node);
    while (!queue.isEmpty()) {
        Node cur = queue.poll();
        System.out.println(cur.value);
        //將節點的所有下游節點加入到隊列
        for (Node next : cur.nexts) {
            if (!set.contains(next)) {
                set.add(next);
                queue.add(next);
            }
        }
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM