状态机过程详解
我们定义三个状态:
- LEFT状态:代表左右子树均未被遍历
- RIGHT状态:代表左子树被遍历
- UP状态:代表左右子树都被遍历过
注意还需要一个栈用于存储遍历路径,方便拿取父节点。
- 实现了这个迭代过程后,我们发现,实际上
LEFT状态
就是前序遍历的操作状态,RIGHT状态
就是中序遍历的操作状态,UP状态
就是后序遍历的操作状态,自此用迭代实现了递归的完全模拟!!!
画出状态转移图
(前序遍历代码)代码
C语言实现:
//定义三种状态,
//LEFT状态代表左右子树均未被遍历
//RIGHT状态代表左子树被遍历
//UP状态代表左右子树都被遍历过
//用栈记录遍历路径
//那么实现前序只需要在LEFT状态下把结点加入答案即可
#define MAXSIZE 100
typedef struct TreeNode TreeNode;
const int LEFT = 1;
const int RIGHT = 2;
const int UP = 3;
int* preorderTraversal(struct TreeNode* root, int* returnSize) {
TreeNode* path[MAXSIZE];//用栈存储路径
int* res = (int*)calloc(MAXSIZE, sizeof(int));
int top = 0;//栈顶指针
int index = 0;//用于更新res的下标
int state = LEFT;//开始时在根节点,左右子树均为被遍历
while (root != NULL) { //三种不同情况的路径处理
if (state == LEFT) {
//由于此时的root是LEFT状态,也就是左右子树都未遍历过,这个状态正好就是前序所需要处理的状态
res[index++] = root->val;
if (root->left != NULL) {
path[top++] = root;
root = root->left;
} else {
state = RIGHT;//如果左子树为空则进入RIGHT状态
}
} else if (state == RIGHT) {
if (root->right != NULL) {
state = LEFT;//注意转移状态
path[top++] = root;
root = root->right;
} else {
state = UP;//如果左右子树均被遍历完,则进入UP状态
}
} else if (state == UP) {
TreeNode* p = NULL;//临时变量用于存储路径双亲结点(如果存在的话)
if (top != 0) { //栈不为空时,得出路径中的上一个结点(肯定是双亲结点)
p = path[top - 1]; top--; //出栈
if (root == p->left) { //如果进入UP状态的结点是它双亲的左子树
state = RIGHT;//则进入RIGHT状态,否则仍然是UP状态
}
}
root = p;
}
}
*returnSize = index;
return res;
}
C++实现:
//定义三种状态,
//LEFT状态代表左右子树均未被遍历
//RIGHT状态代表左子树被遍历
//UP状态代表左右子树都被遍历过
//用栈记录遍历路径
//那么实现前序只需要在LEFT状态下把结点加入答案即可
class Solution {
const int LEFT = 1;
const int RIGHT = 2;
const int UP = 3;
public:
vector<int> preorderTraversal(TreeNode* root) {
vector<int>res;
vector<TreeNode*>path;
int state = LEFT;
while(root){
if(state == LEFT){
res.emplace_back(root->val);
if(root->left){
path.emplace_back(root);
root = root->left;
}else
state = RIGHT;
}
else if(state == RIGHT){
if(root->right){
state = LEFT;
path.emplace_back(root);
root = root->right;
}
else state = UP;
}else if(state == UP){
TreeNode* p = nullptr;
if(!path.empty()){
p = path.back();path.pop_back();
if(root==p->left){
state = RIGHT;
}
}
root = p;
}
}
return res;
}
};