记忆口诀:循环当前,左右到底,右子有无,当前左右,后前前中
后左尾头,右子反转,next开头,首尾相接,遍历反转
0)前中后代码框架
TreeNode *cur=rootr,*temp=nullptr;
while(cur){
temp=cur->left;
if(temp){
while(temp->right&&temp->right!=cur)
temp=temp->right;
if(temp->right){
temp->right=nullptr;
//后序节点处理
}
else{
temp->right=cur;
//前序节点处理
cur=cur->left;
continue;
}
}
else
//前序节点处理
//中序节点处理
cur=cur->right;
}
1)中序
void InOrder(TreeNode* root){//morris中序(左,根,右)
TreeNode *cur=root,*pre=nullptr,*temp=nullptr;
while(cur){
temp=cur->left;
if(temp){
while(temp->right&&temp->right!=cur)
temp=temp->right;
if(temp->right)
temp->right=nullptr;
else{
temp->right=cur;
cur=cur->left;
continue;
}
}
operate(cur),pre=cur;//如果需要用到前驱节点则需定义pre,否则不用
cur=cur->right;
}
}
2)前序
void PreOrder(TreeNode* root){//morris前序(根,左,右)
TreeNode *cur=root,*pre=nullptr,*temp=nullptr;
while(cur){
temp=cur->left;
if(temp){
while(temp->right&&temp->right!=cur)
temp=temp->right;
if(temp->right)
temp->right=nullptr;
else{
temp->right=cur;
operate(cur),pre=cur;//如果需要用到前驱节点则需定义pre,否则不用
cur=cur->left;
continue;
}
}
else
operate(cur),pre=cur;//如果需要用到前驱节点则需定义pre,否则不用
cur=cur->right;
}
}
3)后序
void PostOrder(TreeNode* root){//morris前序(左,右, 根)
TreeNode *cur=root,*pre=nullptr,*temp=nullptr;
while(cur){
temp=cur->left;
if(temp){
while(temp->right&&temp->right!=cur)
temp=temp->right;
if(temp->right){
temp->right=nullptr;
PostHelper(cur->left);
}
else{
temp->right=cur;
cur=cur->left;
continue;
}
}
cur=cur->right;
}
operate(head)
}
void PostHelper(TreeNode* root){
//1 链表(右)逆序,头节点为root
TreeNode *cur=root,*pre=nullptr,*next=nullptr;
while(cur){//next开头,首位相接,方便记忆,如下
next=cur->right;//next=cur->right=pre=cur=next
cur->right=pre;
pre=cur;
cur=next;
}
//2 右边界逆序遍历
cur=pre;//此时头节点为pre
while(cur){
operate(cur);
cur=cur->right;
}
//3 链表(右)逆序,头节点为pre
cur=pre,pre=nullptr,next=nullptr;
while(cur){
next=cur->right;
cur->right=pre;
pre=cur;
cur=next;
}
}