Morris
Morris遍历,应该就是线索二叉树的遍历。 cur为空时,则遍历停止 如果一个节点有左子树,那么一定会来到该节点两次,第一次是第一次遍历,第二次是通过线索来到。
如果一个节点有左子树,则找到左子树的最右节点并且为null,将其指向当前节点,并向左移动。 如果左子树最右节点指向当前节点,则将其置为空,并向右移动 如果一个节点没有左子树,则向右移动
``` c++ "Morris" void Morris(TreeNode head){ if(head==nullptr){ return; } TreeNode cur{head}; TreeNode* most_right{nullptr}; while(cur!=nullptr){ //来到左节点 most_right=cur->left; if(most_right!=nullptr){ //有左子树,则找到最右节点,记得一定是左子树,most_right->right!=cur是为了防止跳出左子树进入右子树 while(most_right->right!=nullptr && most_right->right!=cur){ most_right=most_right->right; } //第一次来到该节点 if(most_right->right == nullptr){ most_right->right=cur; cur=cur->left; //向左移动,直接进入下一次循环 continue; } else{ //第二次来到该节点,将most_right置空,然后向右移动 most_right->right=nullptr; //cur=cur->right; }
}
中序遍历时对于能来到自己两次的节点,第二次打印,对于只能到达自己一次的节点,直接打印
``` c++ "Morris" void MorrisPreOrder(TreeNode head){ if(head==nullptr){ return; } TreeNode cur{head}; TreeNode* most_right{nullptr}; while(cur!=nullptr){ //来到左节点 most_right=cur->left; if(most_right!=nullptr){ //有左子树,则找到最右节点,记得一定是左子树,most_right->right!=cur是为了防止跳出左子树进入右子树 while(most_right->right!=nullptr && most_right->right!=cur){ most_right=most_right->right; } //第一次来到该节点 if(most_right->right == nullptr){ most_right->right=cur; cur=cur->left; //向左移动,直接进入下一次循环 continue; } else{ //第二次来到该节点,将most_right置空,然后向右移动 most_right->right=nullptr; //cur=cur->right; }
}
什么时候用递归套路什么时候用Morris?
如果需要同时获得左右子树的信息并重新整合时只能使用递归套路。否则就可以使用Morris遍历完成相关的遍历题目。
Last updated
Was this helpful?