后序遍历
对于两次到达的节点,在第二次到达的时候,逆序打印左子树右边界这一条链,只到达一次的节点不用管,最后逆序打印整棵树的右边界这条链。
逆序打印链的时候相当于单链表的逆序输出,需要改指针方向,打印之后还需要改回来,由于代码太长,这里只提供思路,详细内容请学习左程云算法进阶班课程。
#include<bits/stdc++.h>
using namespace std;
struct Tree {
int val;
Tree* left;
Tree* right;
Tree(int x){
val = x;
left = right = nullptr;
}
};
void inorder(Tree* root) {
if(!root) return;
inorder(root->left);
cout << root->val << " ";
inorder(root->right);
}
void morrisIn(Tree* root){
if(!root) return;
Tree* cur1 = root;
Tree* cur2 = nullptr;
while(cur1 != nullptr){
cur2 = cur1->left;
if(cur2 != nullptr){ //有左子树
while(cur2->right != nullptr && cur2->right != cur1){
cur2 = cur2->right; //找左子树最右的节点
}
if(cur2->right == nullptr){ //第一次访问
cur2->right = cur1;
cur1 = cur1->left;
continue;
}else{
cur2->right = nullptr; //第二次访问 还原
}
}
cout << cur1->val<<" ";
cur1= cur1->right; //无左子树,直接向右移动
}
}
void morrisPre(Tree* root){
if(!root) return;
Tree* cur1 = root;
Tree* cur2 = nullptr;
while(cur1 != nullptr){
cur2 = cur1->left;
if(cur2 != nullptr){ //有左子树
while(cur2->right != nullptr && cur2->right != cur1){
cur2 = cur2->right; //找左子树最右的节点
}
if(cur2->right == nullptr){ //第一次访问
cur2->right = cur1;
cout << cur1->val<<" "; //先序,第一次到达则访问
cur1 = cur1->left;
continue;
}else{
cur2->right = nullptr; //第二次访问 还原
}
}else{
cout << cur1->val<<" "; //无左子树,直接打印
}
cur1= cur1->right; //无左子树,直接向右移动
}
}
int main() {
Tree* root = new Tree(5);
root->left = new Tree(2);
root->right = new Tree(7);
root->left->left = new Tree(1);
root->left->right = new Tree(4);
root->right->left = new Tree(6);
//inorder(root);
cout<<"Preorder: " ;
morrisPre(root);
cout<<endl<<"Inorder: " ;
morrisIn(root);
return 0;
}