Binary tree pre, middle and post order traversal, iteration and Morris writing records

Posted by PHPnewby! on Tue, 04 Jan 2022 06:35:53 +0100

Binary tree pre, middle and post order traversal, iteration and Morris records

Preorder traversal of binary tree

iteration

class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
vector<int> res;
if (!root) return res;
stack<TreeNode *> stk;
while (root || !stk.empty()) {
while (root) {
res.emplace_back(root->val);
stk.emplace(root);
root = root->left;
}
root = stk.top();
stk.pop();
root = root->right;
}
return res;
}
};

Using the stack, if the root is not empty and the stack is not empty, cycle repeatedly
First, traverse the left node of root, push the value of root into the result in each cycle, and press root into the stack for subsequent extraction to obtain the right node

morris

class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
vector<int> res;
if (!root) return res;
TreeNode *predecessor = nullptr;
while (root) {
predecessor = root->left;
if (predecessor) {
while (predecessor->right && predecessor->right != root) {
predecessor = predecessor->right;
}
if (!predecessor->right) {
res.emplace_back(root->val);
predecessor->right = root;
root = root->left;
continue;
} else {
predecessor->right = nullptr;
}
} else {
res.emplace_back(root->val);
}
root = root->right;
}
return res;
}
};

morris is a little more complicated,
This algorithm requires a temporary node, and the overall loop is performed with root not null
If the root is not null, the node needs to be left first (i.e. = root - > left). If the left bit is not, it will directly push the value of root into the result and let root = root - > right
If yes, the temporary node will be moved to the rightmost first, and the rightmost right will be null. For the first time, the rightmost right will be the position of root at this time, and then move root to the left once. Because it is a pre sequence traversal, the first thing is to push the root value into the result list in advance. If the rightmost right = = root in the next traversal, the temporary node will be null, and root will move to the right node at this time.

Order traversal in binary tree

iteration

class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> res;
stack<TreeNode *> stk;
while (root || !stk.empty()) {
while (root) {
stk.push(root);
root = root->left;
}
root = stk.top();
stk.pop();
res.push_back(root->val);
root = root->right;
}
return res;
}
};

In the second cycle, the root traverses the left node, does not put the result in the list, but first into the stack, and finally traverses FILO top first out of the stack. It indicates that the leftmost node pushes the result first, and then puts root = root - > right

morris

class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> res;
TreeNode* predecessor = nullptr;
while (root != nullptr) {
if (root->left != nullptr) {
predecessor = root->left;
while (predecessor->right != nullptr && predecessor->right != root) {
predecessor = predecessor->right;
}
if (predecessor->right == nullptr) {
predecessor->right = root;
root = root->left;
} else {
res.push_back(root->val);
predecessor->right = nullptr;
root = root->right;
}
} else {
res.push_back(root->val);
root = root->right;
}
}
return res;
}
};

Compared with the previous sequence, morris does not push the results into the result list first after the rightmost, but moves this step to push the value of root into the list if there is root on the rightmost right of the temporary node

Postorder traversal of binary tree

iteration

class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
vector<int> res;
if (!root) return res;
stack<TreeNode *> stk;
TreeNode *prev = nullptr;
while (root || !stk.empty()) {
while (root) {
stk.emplace(root);
root = root->left;
}
root = stk.top();
stk.pop();
if (!root->right || root->right == prev) {
res.emplace_back(root->val);
prev = root;
root = nullptr;
} else {
stk.emplace(root);
root = root->right;
}
}
return res;
}
};

The iteration of the subsequent sequence is quite different. It needs a front node to store the root pushed into the list last time. When the right node of the root in this cycle is empty or not the front node, it will be pushed into the result list. Otherwise, it will be pushed back to the stack and move the root to the right node.

morris

class Solution {
public:
void addPath(vector<int> &vec, TreeNode *node) {
int count = 0;
while (node) {
++count;
vec.emplace_back(node->val);
node = node->right;
}
reverse(vec.end() - count, vec.end());
}

vector<int> postorderTraversal(TreeNode* root) {
vector<int> res;
if (!root) return res;
TreeNode *p1 = root, *p2 = nullptr;
while (p1) {
p2 = p1->left;
if (p2) {
while (p2->right && p2->right != p1) {
p2 = p2->right;
}
if (!p2->right) {
p2->right = p1;
p1 = p1->left;
continue;
} else {
p2->right = nullptr;
}
}
p1 = p1->right;
}