传送门:
添加链接描述
给你一颗二叉树,让你实现中序的遍历
递归没什么好说的,直接无脑递归即可,时间复杂度:O(n),空间复杂度:O(n)
class Solution {
public:void midtravel(TreeNode* root,vector& res){//当节点不为空的时候,递归下去,直到节点为空,则返回上一层,紧接处理节点if (root!=nullptr){midtravel(root->left,res);res.push_back(root->val);midtravel(root->right,res);}}vector inorderTraversal(TreeNode* root) {vector res;midtravel(root,res);return res;}
};
迭代与递归的本质其实是一致的:利用栈来维护每一个节点,只不过递归是隐式的维护了一个栈,而迭代需要你显式的维护一个栈。
图解:
pstack:栈,维护每层的节点
res:vector< int > 存储返回结果
3. 节点4的右子树为空,弹出栈顶元素,弹出节点4,然后加入到res中,此时栈中只剩下了根节点1,弹出节点1,遍历根节点1的右子树,执行同样的操作。
class Solution {
public:vector inorderTraversal(TreeNode* root) {stack pstack;vector res;while (root!=nullptr || !pstack.empty()){while (root!=nullptr){pstack.push(root);root=root->left;}root=pstack.top();pstack.pop();res.push_back(root->val);root=root->right;}return res;}
};
关于线索二叉树的原理及创建,可以看我这篇博客:
线索二叉树的创建解析
线索二叉树提供了无需递归便可以回到以前的节点的方法。
因为线索二叉树的左右指针保存了其当前节点的前驱节点与后继节点的指针,所以可以根据这个线索直接回到之前,不使用栈便可以实现这一操作。
具体实现:
当前节点 x 的左子树为空: 将 x 添加到res中,x=x->right
当前节点 x 的左子树不为空: 找到其左子树的最右端的节点,称作threadnode(当前左子树的中序遍历的最后的一个节点,这个节点即是x的left,然后一直往right,直到到达终点的那个节点)。
图解:
代码示例:
class Solution {
public:vector inorderTraversal(TreeNode* root) {vector res;while (root!=nullptr){if (root->left!=nullptr){//寻找每个节点对应的左子树的最右节点TreeNode* threadnode=root->left;while (threadnode->right!=nullptr && threadnode->right!=root){threadnode=threadnode->right;}if (threadnode->right==nullptr){//右指针线索化threadnode->right=root;root=root->left;}else{//取消线索化res.push_back(root->val);threadnode->right=nullptr;root=root->right;}}else{//到达了某个具有线索的节点,存储与回溯res.push_back(root->val);root=root->right; //保存的线索}}return res;}
};