Morris算法遍历二叉树的时间复杂度为O(N),额外的空间复杂度为O(1)
Morris算法的步骤:
当前节点用cur表示
1)如果cur无左孩子,cur向右移动cur=cur->right
2)如果cur有左孩子,找到cur左子树的最右节点,记为mostright:
如果mostright的右指针为空 让其指向cur,mostright->right=cur,cur向左移动,cur=cur->left;
如果mostright的右指针指向cur 让其指向空 mostright->right=null cur向右移动,cur=cur->right;
如果一个树有左子树,会到达该节点两次,如果没有左子树会到达该节点一次
1
2 3
4 5 7
比如上面的二叉树,首先遍历1 1有左子树,找到左子树的最右节点5 5->right=1 cur=cur->left
遍历2 找到2的左子树的最右节点4 4->>right=2 cur=cur->left
遍历4 4没有左子树 cur=cur->right
cur=2 遍历2 2的左子树的最右节点是4 4->right!=null 4->right=null cur=cur->right
遍历5 5没有左子树 cur=cur->right
cur=1 遍历1 1的左子树的最右节点为5 5->right!=null 5->right=null cur=cur->right
cur=3 遍历3 3无左子树 cur=cur->right
cur=7 遍历7
遍历12425136 只有1 2 有左子树 遍历两次 其他的均遍历一次
void morrisIn(TreeNode*head){
if(head==NULL)
return;
TreeNode*cur=head;
TreeNode*mostRight=NULL;
while(cur!=NULL){
mostRight=cur->left;
if(mostRight!=NULL){//如果有左子树执行
while(mostRight->right!=NULL&&mostRight->right!=cur){
mostRight=mostRight->right;
}
if(mostRight->right==NULL){
mostRight->right=cur;
cur=cur->left;
continue;//相当于是cur将会有第二次访问的机会,所以这次不打印 并且左子树没有访问完 继续往下执行
}else
{
mostRight->right=NULL;
}
}
//std::cout<<cur->val<<" ";
cur=cur->right;
}
}
利用morris算法进行前序遍历
使用递归遍历二叉树,所有的节点都访问3次,选择第一次到达该节点时进行打印 前序遍历 第二次 中序遍历 第三次 后序遍历
对于morris算法
如果一个树有左子树,会到达该节点两次,如果没有左子树会到达该节点一次,没有左子树的节点相当于第一次和第二次合二为一
所以前序遍历就是第一次访问该节点的时候
void morrisPre(TreeNode*head){
if(head==NULL)
return;
TreeNode*cur=head;
TreeNode*mostRight=NULL;
while(cur!=NULL)