Morris遍历
传统的借助栈的二叉树迭代遍历需要O(n)级的内存空间,而Morris迭代遍历借助多个结点指针,可以之用O(1)级的内存空间。
二叉树的结构:
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) {}
};
前序遍历
思路
1、设置结点指针cur指向当前二叉树的根节点。
2、若cur不为空,则继续,否则退出。
3、若cur结点的左孩子不为空,则找到cur结点左孩子的最右结点,用结点指针pre指向该结点。
- 若pre结点的右孩子为空,则让pre的右孩子指向cur,输出cur指向结点的值,cur指向cur的左孩子。重回2。
- 若pre结点的右孩子不为空,则然后将pre的右孩子置空。cur指向其右孩子。重回2。
4、若cur结点的左孩子为空,则输出cur指向结点的值,cur指向cur的右孩子。重回2。
代码实现
vector<int> preorderTraversal(TreeNode *root)
{
vector<int> res;
TreeNode *cur = root;
TreeNode *pre = nullptr;
while (cur)
{
pre = pre->left;
if (pre)
{
while (pre->right && pre->right != cur)
{
pre = pre->right;
}
if (!pre->right)
{
pre->right = cur;
res.push_back(cur->val);
cur = cur->left;
continue;
}
pre->right = nullptr;
}
else
res.push_back(cur->val);
cur = cur->right;
}
return res;
}
中序遍历
思路
1、设置结点指针cur指向当前二叉树的根节点。
2、若cur不为空,则继续,否则退出。
3、若cur结点的左孩子不为空,则找到cur结点左孩子的最右结点,用结点指针pre指向该结点。
- 若pre结点的右孩子为空,则让pre的右孩子指向cur,cur指向cur的左孩子。重回2。
- 若pre结点的右孩子不为空,则然后将pre的右孩子置空。输出cur指向结点的值,cur指向其右孩子。重回2。
4、若cur结点的左孩子为空,则输出cur指向结点的值,cur指向cur的右孩子。重回2。
代码实现
vector<int> inorderTraversal(TreeNode *root)
{
vector<int> res;
TreeNode *cur = root;
TreeNode *pre = nullptr;
while (cur)
{
pre = pre->left;
if (pre)
{
while (pre->right && pre->right != cur)
{
pre = pre->right;
}
if (!pre->right)
{
pre->right = cur;
cur = cur->left;
continue;
}
pre->right = nullptr;
}
res.push_back(cur->val);
cur = cur->right;
}
return res;
}
后序遍历
思路
1、生成一个新的结点指针cur,其左孩子指向当前二叉树的根节点。
2、若cur不为空,则继续,否则退出。
3、若cur结点的左孩子不为空,则找到cur结点左孩子的最右结点,用结点指针pre指向该结点。
- 若pre结点的右孩子为空,则让pre的右孩子指向cur,cur指向cur的左孩子。重回2。
- 若pre结点的右孩子不为空,则然后将pre的右孩子置空。输出cur左孩子到pre结点值的倒序。cur指向其右孩子。重回2。
4、若cur结点的左孩子为空,则cur指向cur的右孩子。重回2。
代码实现
void notePath(vector<int> &res, TreeNode *root)
{
int count = 0;
for (; root; ++count)
{
res.push_back(root->val);
root = root->right;
}
reverse(res.end() - count, res.end());
}
vector<int> inorderTraversal(TreeNode *root)
{
vector<int> res;
TreeNode *cur = new TreeNode();
cur->left = root;
TreeNode *pre = nullptr;
while (cur)
{
pre = pre->left;
if (pre)
{
while (pre->right && pre->right != cur)
{
pre = pre->right;
}
if (!pre->right)
{
pre->right = cur;
cur = cur->left;
continue;
}
pre->right = nullptr;
notePath(res, cur->left);
}
cur = cur->right;
}
return res;
}