Morris二叉树遍历算法
2017-05-19 23:36
176 查看
Morris二叉树遍历算法
时间复杂度O(N),空间复杂度O(1)
这种方法借鉴了线索化二叉树的思想,但是不占用空间
中序遍历方法如下:
如果当前节点的左孩子为空,则输出当前节点并将其右孩子作为当前节点。
如果当前节点的左孩子不为空,在当前节点的左子树中找到当前节点在中序遍历下的前驱节点。
a) 如果前驱节点的右孩子为空,将它的右孩子设置为当前节点。当前节点更新为当前节点的左孩子。
b) 如果前驱节点的右孩子为当前节点,将它的右孩子重新设为空(恢复树的形状)。输出当前节点。当前节点更新为当前节点的右孩子。
重复以上1、2直到当前节点为空。
图例如下:
代码如下
前序遍历方法如下
如果当前节点的左孩子为空,则输出当前节点并将其右孩子作为当前节点。
如果当前节点的左孩子不为空,在当前节点的左子树中找到当前节点在中序遍历下的前驱节点
a). 如果前驱节点的右孩子为空,将它的右孩子设置为当前节点。输出当前节点(
b).如果前驱节点的右孩子为当前节点,将它的右孩子重新设为空。当前节点更新为当前节点的右孩子。
重复以上1、2直到当前节点为空。
示例图:
代码如下
再来看LeetCode99. Recover Binary Search Tree
Q:
Two elements of a binary search tree (BST) are swapped by mistake.
Recover the tree without changing its structure.
Note:
A solution using O(n) space is pretty straight forward. Could you devise a constant space solution?
O(N)空间复杂度很容易想到,将所有节点保存入数组中,遍历即可
这里要求O(1)空间复杂度,所以想到Morris中序遍历
AC解:
引用了Morris二叉树遍历算法,对作者表示感谢!
时间复杂度O(N),空间复杂度O(1)
这种方法借鉴了线索化二叉树的思想,但是不占用空间
中序遍历方法如下:
如果当前节点的左孩子为空,则输出当前节点并将其右孩子作为当前节点。
如果当前节点的左孩子不为空,在当前节点的左子树中找到当前节点在中序遍历下的前驱节点。
a) 如果前驱节点的右孩子为空,将它的右孩子设置为当前节点。当前节点更新为当前节点的左孩子。
b) 如果前驱节点的右孩子为当前节点,将它的右孩子重新设为空(恢复树的形状)。输出当前节点。当前节点更新为当前节点的右孩子。
重复以上1、2直到当前节点为空。
图例如下:
代码如下
/** 1. Definition for a binary tree node. 2. struct TreeNode { 3. int val; 4. TreeNode *left; 5. TreeNode *right; 6. TreeNode(int x) : val(x), left(NULL), right(NULL) {} 7. }; */ class Solution { public: vector<int> inorderTraversal(TreeNode* root) { vector<int> res; TreeNode *cur = root, *prev = nullptr; while (cur) { if (cur->left == nullptr) { res.push_back(cur->val); cur = cur->right; } else { prev = cur->left; while (prev->right != nullptr && prev->right != cur) prev = prev->right; if (prev->right == nullptr) { prev->right = cur; cur = cur->left; } else { res.push_back(cur->val); prev->right = nullptr; cur = cur->right; } } } return res; } };
前序遍历方法如下
如果当前节点的左孩子为空,则输出当前节点并将其右孩子作为当前节点。
如果当前节点的左孩子不为空,在当前节点的左子树中找到当前节点在中序遍历下的前驱节点
a). 如果前驱节点的右孩子为空,将它的右孩子设置为当前节点。输出当前节点(
代码只有这一行不同),当前节点更新为当前节点的左孩子。
b).如果前驱节点的右孩子为当前节点,将它的右孩子重新设为空。当前节点更新为当前节点的右孩子。
重复以上1、2直到当前节点为空。
示例图:
代码如下
class Solution { public: vector<int> preorderTraversal(TreeNode* root) { vector<int> res; TreeNode *cur = root, *prev = nullptr; while (cur) { if (cur->left == nullptr) { res.push_back(cur->val); cur = cur->right; } else { prev = cur->left; while (prev->right != nullptr && prev->right != cur) prev = prev->right; if (prev->right == nullptr) { prev->right = cur; res.push_back(cur->val); cur = cur->left; } else { prev->right = nullptr; cur = cur->right; } } } return res; } };
再来看LeetCode99. Recover Binary Search Tree
Q:
Two elements of a binary search tree (BST) are swapped by mistake.
Recover the tree without changing its structure.
Note:
A solution using O(n) space is pretty straight forward. Could you devise a constant space solution?
O(N)空间复杂度很容易想到,将所有节点保存入数组中,遍历即可
这里要求O(1)空间复杂度,所以想到Morris中序遍历
AC解:
/** * Morris中序遍历,用一组pair存贮第一个和第二个节点 * */ class Solution { public: void recoverTree(TreeNode* root) { TreeNode *cur = root, *prev = nullptr; pair<TreeNode*, TreeNode*> pa; while (cur) { if (cur->left == nullptr) { detect(pa, prev, cur); prev = cur; cur = cur->right; } else { TreeNode *node = cur->left; //prev须时刻为当前遍历节点前驱,用于之后的比较 while (node->right != nullptr && node->right != cur)//所以这里需要有一个node节点用于后面的改造 node = node->right; if (node->right == nullptr) { node->right = cur; cur = cur->left; } else { detect(pa, prev, cur); node->right = nullptr; prev = cur; cur = cur->right; } } } swap(pa.first->val, pa.second->val); } void detect(pair<TreeNode*, TreeNode*>& pa, TreeNode *prev, TreeNode *cur) { if (prev != nullptr && prev->val > cur->val) { if (pa.first == nullptr) pa.first = prev; pa.second = cur; } } };
引用了Morris二叉树遍历算法,对作者表示感谢!
相关文章推荐
- Morris二叉树遍历算法
- 精妙的Morris二叉树遍历算法
- 精妙的Morris二叉树遍历算法
- Morris二叉树遍历算法
- Morris二叉树遍历算法
- Morris二叉树遍历算法
- Morris二叉树遍历算法
- Morris二叉树遍历算法
- Morris病毒
- 算法导论-第32章-字符串匹配:Knuth-Morris-Pratt(KMP)算法C++实现
- KMP(Knuth-Morris-Pratt)算法
- 二叉树的四种遍历方式:递归、非递归+栈、Morris(后序非递归还有一种单栈和双栈的不同版本)
- 二叉树遍历算法的应用
- leetcode 99. Recover Binary Search Tree 二叉树非递归遍历,利用stack和morris遍历
- 0-引言:Morris蠕虫现在还有用吗
- ZOJ - 3957 Knuth-Morris-Pratt Algorithm
- [zhuan]二叉树遍历算法实现(C#2.0)
- [转]二叉树遍历算法实现(C#2.0)
- KMP算法 Knuth-Morris-Pratt 字符串查找算法
- 笔试算法题(52):简介 - KMP算法(D.E. Knuth, J.H. Morris, V.R. Pratt Algorithm)