题目来源
题目描述
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) {
}
}
题目解析
morrios遍历
void morris(TreeNode * head){
if(head == nullptr){
return;
}
TreeNode *curr = head;
TreeNode *mostRight = nullptr;
while (curr != nullptr){
mostRight = curr->left;
if(mostRight == nullptr){
printf("%d\t", curr->val);
curr = curr->right;
}else{
while (mostRight->right != nullptr && mostRight->right != curr){
mostRight = mostRight->right;
}
if(mostRight->right == nullptr){
mostRight->right = curr;
curr = curr->left;
}else{
printf("%d\t", curr->val);
mostRight->right = nullptr;
curr = curr->right;
}
};
}
}
递归
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> ans;
helper(root, ans);
return ans;
}
private:
void helper(TreeNode* root, vector<int> & ans){
if(root == NULL){
return ;
}
helper(root->left, ans);
ans.emplace_back(root->val);
helper(root->right, ans);
}
};
null标记法
- 入栈顺序: 右、中、null、左
vector<int> inorderTraversal(TreeNode* root) {
vector<int> vec;
if(root == NULL){
return vec;
}
std::stack<TreeNode *> stack;
stack.emplace(root);
while (!stack.empty()){
TreeNode *peek = stack.top();
stack.pop();
if(peek == NULL){
vec.emplace_back(stack.top()->val);
stack.pop();
}else{
if(peek->right){
stack.push(peek->right);
}
stack.push(peek);
stack.push(NULL);
if(peek->left){
stack.push(peek->left);
}
}
}
return vec;
}
颜色标记法
“颜色标记法”,兼具栈迭代方法的高效,又像递归方法一样间接易懂,更重要的是,这种方法对于前序、中序、后序遍历,能够写出完全一致的代码。
其核心思想如下:
- 如果颜色标记节点的状态,新节点为白色,已访问节点为灰色
- 如果遇到的节点为白色,那么将其标记为灰色,然后将其右子节点、自身、左子节点依次入栈
- 如果遇到的节点为灰色,那么将其节点的值输出。
解释一下为什么需要“右子节点、自身、左子节点依次入栈”
- 我们有一颗二叉树
- 前序遍历:中、左、右
- 中序遍历:左、中、右
- 后序遍历:左、右、中
中
/ \
左 右
- 如果需要中序遍历。
- 栈是先进后出的结构,出栈顺序需要为: 左、中、右
- 所以,入栈顺序必须倒序: 右、中、左
- 同理,如果是前序遍历,入栈顺序为 右,左,中;后序遍历,入栈顺序中,右,左
使用这种方法实现的中序遍历如下:
typedef int STATUS;
STATUS WHITE = 0;
STATUS GRAP = 1;
vector<int> inorderTraversal(TreeNode* root) {
vector<int> vec;
if(root == NULL){
return vec;
}
std::stack<std::pair<STATUS, TreeNode *>> stack;
stack.push({WHITE, root});
while (!stack.empty()){
STATUS status = stack.top().first;
TreeNode * node = stack.top().second;
stack.pop();
if(status == WHITE){
if( node->left != NULL){
stack.push({WHITE, node->left});
}
stack.push({GRAP, node});
if( node->right != NULL){
stack.push({WHITE, node->right});
}
}else{
vec.emplace_back(node->val);
}
}
return vec;
}
如要实现前序、后序遍历,只需要调整左右子节点的入栈顺序即可。