方法有三个:
- Morris 中序遍历:时间复杂度 O ( N ) O(N) O(N),空间复杂度 O ( 1 ) O(1) O(1)
- 递归遍历:时间复杂度 O ( N ) O(N) O(N),空间复杂度 O ( N ) O(N) O(N)(递归栈)
- 迭代遍历:时间复杂度 O ( N ) O(N) O(N),空间复杂度 O ( N ) O(N) O(N)
Morris 中序遍历:
不适用额外的存储空间,通过改变节点的指向完成遍历。当前访问节点为root:
1.若当前节点不存在左子树
- 将节点值输出
- 当前节点向右移动
2.若当前节点存在左子树:
- 找到左子树中序遍历的最后一个节点【前驱节点:左-右-右-…-右】
- 若前驱节点右节点为空
– 右节点指向当前root
– root = root → \rightarrow → left - 若前驱节点右节点不为空
– 当前值输出
– root = root → \rightarrow → right
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> out;
TreeNode* preds = root;
while(root){
if(!root->left) {
out.push_back(root->val);
root = root->right;
} else {
preds = root->left;
while(preds->right && preds->right != root) preds = preds->right;
if(!preds->right) {
preds->right = root;
root = root->left;
}
else {
out.push_back(root->val);
preds->right = nullptr;
root = root->right;
}
}
}
return out;
}
};
递归遍历:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
vector<int> out;
void inorder(TreeNode* node) {
if(!node) return;
if(node->left) inorder(node->left);
out.push_back(node->val);
if(node->right) inorder(node->right);
}
public:
vector<int> inorderTraversal(TreeNode* root) {
inorder(root);
return out;
}
};
迭代遍历(堆):
出栈的时,存储输出值。
root 指针不断更新,对于每一个子树:
左边向下,用一个 while 找到最深的叶子节点
右边返回,当前节点先出栈,再访问右节点
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> out;
stack<TreeNode*> stk;
while(root || stk.size() > 0){
while(root){
stk.push(root);
root = root->left;
}
root = stk.top();
stk.pop();
out.push_back(root->val);
root = root->right;
}
return out;
}
};
另一种迭代(较好理解)每一个节点存入栈中时记录其相应的访问状态
若已经访问过, 则加入输出
否则,按照出栈中序遍历的顺序压入栈中
附上代码:
typedef pair<int, TreeNode*> P;
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> out;
stack<P> stk;
stk.push(P(0, root));
while(stk.size() > 0) {
P temp = stk.top();
stk.pop();
if(!temp.second) continue;
if(!temp.first) {
stk.push(P(0, temp.second->right));
stk.push(P(1, temp.second));
stk.push(P(0, temp.second->left));
} else {
out.push_back(temp.second->val);
}
}
return out;
}
};