LC144/94/145 二叉樹前序/中序/後序遍歷 遞迴與非遞迴實現
阿新 • • 發佈:2020-07-13
前序遍歷
遞迴寫法
class Solution { public: vector<int> preorderTraversal(TreeNode* root) { vector<int> res, leftRes, rightRes; if(root == nullptr) return res; res.push_back(root->val); leftRes = preorderTraversal(root->left); rightRes = preorderTraversal(root->right); if(leftRes.size() > 0) { for(auto val : leftRes) res.push_back(val); } if(rightRes.size() > 0) { for(auto val : rightRes) res.push_back(val); } return res; } };
遞迴寫法的時間複雜度,空間複雜度較為一般。
非遞迴寫法
使用非遞迴寫法時需要用到棧,這裡採用了LC題解中一種不錯的解法.
思路:帶有nullptr標記的節點直接訪問節點值,沒有標記則對節點本身新增標記並遍歷子節點,該過程用棧實現
class Solution { public: vector<int> preorderTraversal(TreeNode* root) { vector<int> res; if(root == nullptr) return res; stack<TreeNode*> nodes; nodes.push(root); while(nodes.size() > 0){ TreeNode* nowNode = nodes.top(); nodes.pop(); if(nowNode != nullptr){ // 右 if(nowNode->right != nullptr) nodes.push(nowNode->right); // 左 if(nowNode->left != nullptr) nodes.push(nowNode->left); // 根 nodes.push(nowNode); nodes.push(nullptr); } else{ res.push_back(nodes.top()->val); nodes.pop(); } } return res; } };
這個題解的優點在於只需要交換 //右,//左,//根三部分的順序即可實現先序/中序/後序遍歷方式,非常方便.
下圖是一個遍歷過程圖示,可以更清晰地看到遍歷過程。
中序遍歷
遞迴寫法
class Solution { public: vector<int> inorderTraversal(TreeNode* root) { vector<int> res, leftRes, rightRes; if(root == nullptr) return res; leftRes = inorderTraversal(root->left); rightRes = inorderTraversal(root->right); if(!leftRes.empty()){ for(auto val : leftRes) res.push_back(val); } res.push_back(root->val); if(!rightRes.empty()){ for(auto val : rightRes) res.push_back(val); } return res; } };
非遞迴寫法
參考前序遍歷的非遞迴寫法即可
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> res;
if(root == nullptr)
return res;
stack<TreeNode*> nodes;
nodes.push(root);
while(!nodes.empty()){
TreeNode* nowNode = nodes.top();
nodes.pop();
if(nowNode != nullptr){
// 右
if(nowNode->right != nullptr)
nodes.push(nowNode->right);
// 根
nodes.push(nowNode);
nodes.push(nullptr);
// 左
if(nowNode->left != nullptr)
nodes.push(nowNode->left);
}
else{
res.push_back(nodes.top()->val);
nodes.pop();
}
}
return res;
}
};
後序遍歷
遞迴
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
vector<int> res, left, right;
if(root == NULL)
return res;
left = postorderTraversal(root->left);
right = postorderTraversal(root->right);
for(auto iter = left.begin(); iter != left.end(); iter ++)
res.push_back(*iter);
for(auto iter = right.begin(); iter != right.end(); iter ++)
res.push_back(*iter);
res.push_back(root->val);
return res;
}
};
非遞迴
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
vector<int> res;
if(root == nullptr)
return res;
stack<TreeNode*> nodes;
nodes.push(root);
while(!nodes.empty()){
TreeNode* nowNode = nodes.top();
nodes.pop();
if(nowNode != nullptr){
// 根
nodes.push(nowNode);
nodes.push(nullptr);
// 右
if(nowNode->right != nullptr)
nodes.push(nowNode->right);
// 左
if(nowNode->left != nullptr)
nodes.push(nowNode->left);
}
else{
res.push_back(nodes.top()->val);
nodes.pop();
}
}
return res;
}
};