Morris遍历(先序和中序)

后序遍历

对于两次到达的节点,在第二次到达的时候,逆序打印左子树右边界这一条链,只到达一次的节点不用管,最后逆序打印整棵树的右边界这条链。
逆序打印链的时候相当于单链表的逆序输出,需要改指针方向,打印之后还需要改回来,由于代码太长,这里只提供思路,详细内容请学习左程云算法进阶班课程。

#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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值