面试题(十四)Morris遍历

二叉树的Morris遍历,是一种无堆栈,无递归,空间复杂度O(1)的高效遍历算法,这个算法在遍历的过程中需要改变二叉树的叶子节点的又指针域,即原来为NULL的要发生变化,但是遍历完成以后,过程中的变化又会恢复,所以遍历前,遍历后,二叉树不发生任何改变。

先给出伪代码,网上的

MorrisInOrder():
while 没有结束

   如果当前节点没有左后代

     访问该节点
     转向右节点

   否则

     找到左后代的最右节点,且使最右节点的右指针指向当前节点
     转向左后代节点

 

现在先考虑中序遍历,左,中,右

即整个代码分为两个部分,

1:对于没有左后代的节点:

说明应该访问该节点,然后当前节点指向其右孩子

2:对于有左后代的节点:

当前节点应该继续指向其左孩子,说到这,前面的逻辑关系跟其他递归形式的遍历一样,Morris这时候,是将其左孩子的最右节点指向自己,即:左之最右指向自己

执行过程中,在当前节点依次向左节点移动的过程中,一层一层的将左子树的最右指向自己

 

为啥要这样做呢?

这是为了在当前节点到达叶子节点的时候能够回去,前面2做的工作是给后面的铺路,确保当前节点跑到叶子节点的时候能回朔;这样就能理解1为啥左子树为空的时候可以指向右子树,这是因为前面已经铺好了道路

 

还有一个:就是过河拆桥,我前面铺了路,后面的人走完了以后要帮我把那条路清除,就是过河拆桥,这样做不是为了不改变二叉树结构,而是必须这么做,如果不这么做,那么二叉树首先逻辑混乱,其次我前面的左之最后指向自己就没法正确执行,因为最右指向了自己,我如果再这么执行,那么这个最右不知跳到哪儿去了

过河拆桥的细节体现在

while(pTemp->right!=NULL&&pTemp->right!=pCur)这个&&以后的语句上

代码如下:

void morris(Node *pRoot)
 {
 	Node *pCur=pRoot;
 	Node *pTemp;
 	while(pCur)
 	{	
 		if (pCur->left==NULL)
 		{
 			cout<<pCur->nData<<'\t';
 			pCur=pCur->right;
 		}
 		else
 		{
 			pTemp=pCur->left;
 			while(pTemp->right!=NULL&&pTemp->right!=pCur)
 			{
 				pTemp=pTemp->right;
 			}
 			if (pTemp->right=NULL)
	//这里执行左之最右指向自己,然后当前节点向左移,这里是第一次	
 			{
 				pTemp->right=pCur;
 				pCur=pCur->left;
 			}
 			else 
	//下面的工作是拆桥,对于pCur来说已经不能向左走了,因为我刚从左边过来,所以向右走 
 			{
 				pTemp->right=NULL;
 				pCur=pCur->right;
 			}
 		}
 	}
 }

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值