tree traversal (樹的遍歷) - 層序遍歷 (level order traversal) - 二叉樹的層序遍歷

tree traversal (樹的遍歷) - 層序遍歷 (level order traversal) - 二叉樹的層序遍歷

1. tree traversal (樹的遍歷)

1.1 深度優先搜索 (depth-first search,DFS)

我們採用深度作爲優先級,從根節點開始一直到達某個確定的葉子節點,然後再返回根節點到達另一個分支。深度優先搜索策略可以根據根節點、左孩子樹和右孩子樹的相對順序被細分爲前序遍歷、中序遍歷和後序遍歷。

前序遍歷 (preorder traversal) - 中序遍歷 (inorder traversal) - 後序遍歷 (postorder traversal)

1.2 廣度優先搜索 - 寬度優先搜索 - 橫向優先搜索 (breadth-first search,BFS)

我們按照高度順序一層一層的訪問整棵樹,高層次的節點將會比低層次的節點先被訪問到。

下圖中的節點依照不同的策略遍歷,訪問的順序均爲 1, 2, 3, 4, 5。寬度優先搜索劃分層次爲 [[1], [2, 3], [4, 5]]
在這裏插入圖片描述

遞歸實現的效率一般比對應的非遞歸實現低。如果在函數中使用了兩個遞歸調用,效率低下的問題就會變得更爲嚴重。

2. 二叉樹的層序遍歷

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

2.1 示例

二叉樹:[3,9,20,null,null,15,7]

    3
   / \
  9  20
    /  \
   15   7

返回其層次遍歷結果:

[
  [3],
  [9,20],
  [15,7]
]

2.2 Source Code

//============================================================================
// Name        : level_order
// Author      : Yongqiang Cheng
// Version     : Version 1.0.0
// Copyright   : Copyright (c) 2019 Yongqiang Cheng
// Description : Hello World in C++, Ansi-style
//============================================================================

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution
{
public:
    vector<vector<int>> levelOrder(TreeNode* root)
    {
        vector<vector<int>> ret_data = { };
        queue<TreeNode *> queue_data = { };
        TreeNode *proot = root;
        TreeNode *front_data = NULL;

        if (NULL == root)
        {
            return {};
        }

        queue_data.push(proot);

        while (!queue_data.empty())
        {
            vector<int> tmp = { };
            int queue_size = queue_data.size();

            for (int idx = 0; idx < queue_size; idx++)
            {
                front_data = queue_data.front();
                queue_data.pop();
                tmp.push_back(front_data->val);

                if (NULL != front_data->left)
                {
                    queue_data.push(front_data->left);
                }

                if (NULL != front_data->right)
                {
                    queue_data.push(front_data->right);
                }
            }

            ret_data.push_back(tmp);
        }

        return ret_data;
    }
};

在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述

2.3 遞歸實現

遞歸實現較爲簡單,首先確認樹非空,然後調用遞歸函數 helper(node, level),參數是當前節點和節點的層次。程序過程如下:

  • 輸出列表稱爲 levels,當前最高層數就是列表的長度 len(levels)。比較訪問節點所在的層次 level 和當前最高層次 len(levels) 的大小,如果前者更大就向 levels 添加一個空列表。
  • 將當前節點插入到對應層的列表 levels[level] 中。
  • 遞歸非空的孩子節點:helper(node.left / node.right, level + 1)

在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

在這裏插入圖片描述

複雜度分析

  • 時間複雜度:O(N),每個節點恰好會被運算一次。
  • 空間複雜度:O(N),保存輸出結果的數組包含 N 個節點的值。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章