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
個節點的值。