1. 程式人生 > >二叉樹DFS和BFS 遞迴/非遞迴

二叉樹DFS和BFS 遞迴/非遞迴

二叉樹DFS和BFS 遞迴/非遞迴方式

1.DFS

DFS, 深度優先遍歷
(1)遞迴形式

public class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int x) { val = x; }
}
List<TreeNode> list = new ArrayList<>();
public List<TreeNode> traversal(TreeNode root) {
    dfs(root);
    return list;
}

private void dfs(TreeNode root) {
    if (root == null) return;
    list.add(root);
    dfs(root.left);
    dfs(root.right);
}

(2)非遞迴形式 (利用棧來遞迴)

public List<TreeNode> traversal(TreeNode root) {
    if (root == null) return null;
    List<TreeNode> res = new ArrayList<>();
    Stack<TreeNode> stack = new Stack<>();
    stack.add(root);
    while(!stack.empty()) {
        TreeNode node = stack.pop();
        res.add(node);
        if (node.right != null) {
            stack.push(node.right);
        }
        if (node.left != null) {
            stack.push(node.left);
        }
    }
    return res;
}

2.BFS

BFS,廣度優先遍歷,對應二叉樹的層級遍歷
(1)非遞迴形式 (利用佇列實現遍歷)

public List<TreeNode> traversal(TreeNode root) {
        if (root == null) return null;
        return bfs(root);
    }

    private List<TreeNode> bfs(TreeNode root) {
        //if (root == null) return null;
        int curNum = 1;   //維護當前層的node數量
        int nextNum = 0;  //維護下一層的node數量
        Queue<TreeNode> queue = new LinkedList<>();
        List<TreeNode> list = new ArrayList<>();
        queue.offer(root);
        while(!queue.isEmpty()) {
            TreeNode node = queue.poll();
            list.add(node);
            curNum--;
            if (node.left != null) {
                queue.add(node.left);
                nextNum++;
            }
            if (node.right != null) {
                queue.add(node.right);
                nextNum++;
            }

            if (curNum == 0) {
                curNum = nextNum;
                nextNum = 0;
            }
        }

        return list;
    }

(2)遞迴形式
這裡所謂的bfs遞迴形式,是利用dfs的遞迴形式,在遞迴過程中記錄每個node的level,然後將屬於一個level的node放到一list裡面

public List<List<TreeNode>> traversal(TreeNode root) {
    if (root == null) return null;
    List<List<TreeNode>> list = new ArrayList<>();
    dfs(root, 0, list);
    return list;
}

private void dfs(TreeNode root, int level, List<List<TreeNode>> list) {
    if (root == null) return;
    if (level >= list.size()) {
        List<TreeNode> subList = new ArrayList<>();
        subList.add(root);
        list.add(subList);
    } else {
        list.get(level).add(root);
    }
    dfs(root.left, level+1, list);
    dfs(root.right, level+1, list);
}

圖的深度優先遍歷和廣度優先遍歷,和二叉樹的dfs、bfs原理的相同的。一般,深度優先遍歷利用棧來實現(或者遞迴),廣度優先遍歷利用佇列來實現。