1. 程式人生 > 其它 >寬度優先搜尋BFS的三種實現方法(單佇列,雙佇列,哨兵)——二叉樹的層序遍歷102

寬度優先搜尋BFS的三種實現方法(單佇列,雙佇列,哨兵)——二叉樹的層序遍歷102

寬度優先搜尋

題目:二叉樹的層序遍歷

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

輸入:[3,9,20,null,null,15,7]

    3
   / \
  9  20
    /  \
   15   7

輸出:[[3],[9,20],[15,7]]

思路:利用BFS遍歷二叉樹,輸出每層遍歷的值

1.單佇列

非遞迴實現:

class Solution {
        public List<List<Integer>> levelOrder(TreeNode root) {
            List<List<Integer>> res = new ArrayList<>();
            if (root == null) return res;

            Queue<TreeNode> queue = new LinkedList<>();
            queue.add(root);

            while (!queue.isEmpty()) {
                int length = queue.size();
                List<Integer> list = new ArrayList<>();

                for (int i = 0; i < length; i++) {
                    TreeNode temp = queue.poll();
                    list.add(temp.val);

                    if (temp.left != null)
                        queue.add(temp.left);
                    if (temp.right != null)
                        queue.add(temp.right);
                }
                res.add(list);
            }

            return res;
        }
    }

遞迴實現:

class Solution {
        private List<List<Integer>> res;

        public void bfs(Queue<TreeNode> queue) {
            if (queue.isEmpty()) return;

            List<Integer> list = new ArrayList<>();
            int length = queue.size();

            for (int i = 0; i < length; i++) {
                TreeNode temp = queue.poll();
                list.add(temp.val);

                if (temp.left != null)
                    queue.add(temp.left);
                if (temp.right != null)
                    queue.add(temp.right);
            }
            res.add(list);
            bfs(queue);
        }

        public List<List<Integer>> levelOrder(TreeNode root) {
            res = new ArrayList<>();
            if (root == null) return res;

            Queue<TreeNode> queue = new LinkedList<>();
            queue.add(root);
            bfs(queue);

            return res;
        }
    }

2. 雙佇列

用兩個佇列輪次儲存當前節點和下層節點。

class Solution {
        public List<List<Integer>> levelOrder(TreeNode root) {
            List<List<Integer>> res = new ArrayList<>();
            if (root == null) return res;

            List<TreeNode> queue = new ArrayList<>();
            queue.add(root);

            while (!queue.isEmpty()) {
                List<TreeNode> queue2 = new ArrayList<>();
                List<Integer> level = new ArrayList<>();

                for (TreeNode node : queue) {
                    level.add(node.val);
                    if (node.left != null)
                        queue2.add(node.left);
                    if (node.right != null)
                        queue2.add(node.right);
                }
                res.add(level);
                queue = queue2;
            }
            return res;
        }
    }

3. 哨兵

哨兵:頭節點之前的空節點,始終指向頭結點。

在佇列中,在每一層後加一個空的節點,用來區別不同的層。遍歷每一層時,如果當前佇列的為null時,則在佇列末尾即下一層新增一個null。

class Solution {
        public List<List<Integer>> levelOrder(TreeNode root) {
            List<List<Integer>> res = new ArrayList<>();
            if (root == null) return res;

            Queue<TreeNode> queue = new LinkedList<>();
            queue.add(root);
            queue.add(null);

            List<Integer> level = new ArrayList<>();
            while (!queue.isEmpty()) {
                TreeNode temp = queue.poll();
                if (null == temp) {
                    res.add(level);
                    if (queue.isEmpty())
                        break;

                    queue.add(null);
                    level = new ArrayList<>();
                    continue;
                }

                level.add(temp.val);
                if (temp.left != null)
                    queue.add(temp.left);
                if (temp.right != null)
                    queue.add(temp.right);
            }
            return res;
        }
    }