二叉树的遍历主要有三种方法:前序遍历、中序遍历和后序遍历。这三种方法的非递归实现形式各有特点,较为复杂。然而,有一种通用的遍历方法——颜色标记法,可以应用于前序、中序、后序以及层次遍历。
之前笔试题遇到非递归遍历二叉树,平时都是递归写的,猝不及防的翻车了,在leetcode看见了这个方法,很神奇,基本都是100%击败,而且一套通用前序、中序、后序,学会了以后麻麻再也不用担心面试遇到写非递归遍历二叉树了,
学之前:各种奇怪的姿势利用栈模拟来遍历二叉树;
学之后:自信.jpg, 王之藐视.jpg,一套通杀!
一、方法解释
颜色标记法使用颜色来标识节点的状态。新访问的节点被标记为白色,已访问过的节点则为灰色。在遍历过程中,每当我们遇到一个白色节点,我们就将其标记为灰色,并将它和它的左右子节点依次压入栈中。如果遇到的节点是灰色的,则直接输出该节点的值。这种方法的优点在于其适用于各种类型的二叉树遍历,使得代码更加简洁并易于理解。
二、代码实现
struct TreeNode {
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
// 中序遍历
vector<int> inorderTraversal(TreeNode* root) {
int white = 0, gray = 1;
vector<int> res;
vector<pair<int, TreeNode*>> stk;
stk.push_back({white, root});
while(!stk.empty()){
auto [color, node] = stk.back();
stk.pop_back();
if(node == nullptr) continue;
if(color == white){
stk.push_back({white, node->right});
stk.push_back({gray, node});
stk.push_back({white, node->left});
} else {
res.push_back(node->val);
}
}
return res;
}
// 前序遍历
vector<int> preorderTraversal(TreeNode* root) {
int white = 0, gray = 1;
vector<int> res;
vector<pair<int, TreeNode*>> stk;
stk.push_back({white, root});
while(!stk.empty()){
auto [color, node] = stk.back();
stk.pop_back();
if(node == nullptr) continue;
if(color == white){
stk.push_back({white, node->right});
stk.push_back({white, node->left});
stk.push_back({gray, node});
} else {
res.push_back(node->val);
}
}
return res;
}
// 后序遍历
vector<int> postorderTraversal(TreeNode* root) {
int white = 0, gray = 1;
vector<int> res;
vector<pair<int, TreeNode*>> stk;
stk.push_back({white, root});
while(!stk.empty()){
auto [color, node] = stk.back();
stk.pop_back();
if(node == nullptr) continue;
if(color == white){
stk.push_back({gray, node});
stk.push_back({white, node->right});
stk.push_back({white, node->left});
} else {
res.push_back(node->val);
}
}
return res;
}
三、知识点练习
交封面图不杀,开始摇摆,耶~