二叉樹的遍歷包括先序遍歷,中序遍歷,後序遍歷,層次遍歷等等。本文對此進行整理。
二叉樹結構定義如下:
//Definition for binary tree
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
1. 先序遍歷
先序遍歷就是先訪問根節點,然後再先序遍歷左子樹,最後先序遍歷右子樹。先序遍歷也就是深度優先搜索(DFS)。
先序遍歷遞歸實現:
vector<int> preorderTraversal(TreeNode *root)
{
vector<int> vals;
preorderTraversal(root, vals);
return vals;
}
void preorderTraversal(TreeNode *root, vector<int> &vals)
{
if(root == NULL) return;
vals.push_back(root->val);
preorderTraversal(root->left, vals);
preorderTraversal(root->right, vals);
}
先序遍歷非遞歸實現:
vector<int> preorderTraversal(TreeNode * root)
{
vector<int> vals;
stack<TreeNode*> s;
TreeNode * p = root;
while(!s.empty() || p)
{
if(p == NULL)
{
while(!s.empty() && (p == s.top()->right || s.top()->right == NULL))
{ // 右子樹已訪問,出棧
p = s.top();
s.pop();
}
if(s.empty()) break;
// 左子樹已訪問,右子樹尚未訪問,訪問右子樹
p = s.top()->right;
}
else
{
vals.push_back(p->val);
s.push(p);
p = p->left;
}
}
return vals;
}
2. 中序遍歷
中序遍歷就是先中序遍歷左子樹,然後訪問根節點,最後中序遍歷右子樹。
中序遍歷遞歸實現:
vector<int> inorderTraversal(TreeNode *root)
{
vector<int> vals;
inorderTraversal(root, vals);
return vals;
}
void inorderTraversal(TreeNode *root, vector<int> &vals)
{
if(root == NULL) return;
inorderTraversal(root->left, vals);
vals.push_back(root->val);
inorderTraversal(root->right, vals);
}
中序遍歷非遞歸實現:
vector<int> inorderTraversal(TreeNode *root) {
vector<int> vals;
stack<TreeNode *> s;
TreeNode *p = root;
while(!s.empty() || p)
{
while(p)
{
s.push(p);
p = p->left;
}
p = s.top();
s.pop();
vals.push_back(p->val);
p = p->right;
}
return vals;
}
3. 後序遍歷
後序遍歷就是先後序遍歷左子樹,再後序遍歷右子樹,最後訪問根節點。
後序遍歷遞歸實現:
vector<int> postorderTraversal(TreeNode* root)
{
vector<int> vals;
postorderTraversal(root, vals);
return vals;
}
void postorderTraversal(TreeNode *root, vector<int> &vals)
{
if(root == NULL)
return;
postorderTraversal(root->left, vals);
postorderTraversal(root->right, vals);
vals.push_back(root->val);
}
後序遍歷非遞歸實現:
vector<int> postorderTraversal(TreeNode* root)
{
vector<int> vals;
stack<TreeNode*> s;
TreeNode * pre = NULL;
TreeNode * p = root;
while(!s.empty() || p)
{
while(p)
{
s.push(p);
p = p->left;
}
pre = NULL;
while(!s.empty() && pre == s.top()->right)
{
pre = s.top();
vals.push_back(s.top()->val);
s.pop();
}
if(s.empty()) break;
p = s.top()->right;
}
return vals;
}
4. 層次遍歷
層次遍歷就是先遍歷第一層節點,然後遍歷第二層節點,。。。也就是廣度優先搜索(BFS)。
隊列實現:
vector<int> levelOrderTraversal(TreeNode *root)
{
vector<int> vals;
if(root == NULL)
return vals;
queue<TreeNode*> q;
q.push(root);
while(!q.empty())
{
TreeNode * p = q.front();
q.pop();
vals.push_back(p->val);
if(p->left)
q.push(p->left);
if(p->right)
q.push(p->right);
}
return vals;
}
層次遍歷遞歸實現:
vector<int> levelOrderTraversal(TreeNode *root)
{
vector<int> vals;
height = getTreeHeight(root);
for(int level = 1; level <= height; level++)
levelOrderTraversal(root, level, vals);
return vals;
}
int getTreeHeight(TreeNode * root)
{
if(root == NULL) return 0;
int heightLeft = getTreeHeight(root->left);
int heightRight = getTreeHeight(root->right);
return max(heightLeft, heightRight)+1;
}
void levelOrderTraversal(TreeNdoe *root, int level, vector<int> &vals)
{
if(root == NULL) return;
if(level == 1)
{
vals.push_back(root->val);
return;
}
levelOrderTraversal(root->left, level-1, vals);
levelOrderTraversal(root->right, level-1, vals);
}
注意,此實現時間複雜度仍然爲O(n).