由反序列化二叉树实现函数引起的二叉树节点递归调用问题

          在刷剑指offer中遇到一个反序列化二叉树问题,将给定的二叉树前序遍历字符串(节点之间用“,”分割,空节点我用的“#”)。代码用递归很容易实现,由于递归中不保存int型数据,为了给字符串遍历计数,用了一个只有一个元素的数组(目前没有想到更好的方法,返回值其他值已被预订)   实现方法如下:

public class Demo {
    
	TreeNode Deserialize(String str) {
		if(str.length()<=0)
			return null;
		String[] strArray=str.split(","); 
		TreeNode pHead=new TreeNode(Integer.parseInt(strArray[0]));		
		int[] array1=new int [1];
		array1[0]=0;
		deseiriaImp(pHead,strArray,array1);
		return pHead;		       
  }
	
  private void deseiriaImp(TreeNode node,String[] strArray, int[] array1) {
	    if( strArray[array1[0]].equals("#") || (array1[0]==strArray.length))
	    {		    	
	    	array1[0]++;
	    	return ;
	    }
	        node=new TreeNode(Integer.parseInt(strArray[array1[0]]));
	    	array1[0]++;	    	
	    	deseiriaImp(node.left,strArray,array1);			    			 
	    	deseiriaImp(node.right,strArray,array1);	    	
		     		     	    		    		   		    
	}



public static void main(String[] args)
	{
	TreeNode node1=new TreeNode(1);
	TreeNode node2=new TreeNode(2);
	TreeNode node3=new TreeNode(3);
	TreeNode node4=new TreeNode(4);
	TreeNode node5=new TreeNode(5);
	TreeNode node6=new TreeNode(6);		
    node1.left= node2;
    node1.right=node3;    
    node2.left= node4;
    node2.right=null ;    
    node3.left=node5 ;
    node3.right= node6;   
    node4.left= null;
    node4.right=null;
    node5.left= null;
    node5.right=null;
    node6.left= null;
    node6.right=null ;		   
    String seriaStr="1,2,4,#,#,#,3,5,#,#,6,#,#";	     
    new Demo().Deserialize(seriaStr);					 
	}	
}

调试结果(调用递归函数后,pHead的值):


        但是结果却不对,返回的pHead的值为1,子树为空!我调试进递归函数发现运算程序是对的呀。我一度开始怀疑对象在调用中不是直接引用的,而是像基本类型变量一样复制的。为此,做了个实验,在实验中同样参数为一个非空的节点,但是在调用函数中给节点参数加上非空子节点,并改变节点参数的值,然后看pHead子节点有没有改变。代码如下:

public class Test {
    
	void testNode(TreeNode node)
	{
		node.val=6;
		node.left=new TreeNode(2);
		node.right=new TreeNode(3);		
	}

 public static void main(String[] args)
	{	 
	 TreeNode node1=new TreeNode(1);
	 new Test().testNode(node1);
	 System.out.println(node1.val);	 
	}   
}


      实验结果:


     这里实验结果证明,调用函数里的对象是直接引用的,而不是复制的。反序列化二叉树的代码也没问题呀。后来不得不改变的策略:用递归函数返回头结点。代码其他地方完全没有变,只是加了返回值,然后将返回值赋给引用节点的左右节点。还是贴出完整代码(为了调试没有直接返回递归结果):

public class Solution
{  	
		TreeNode Deserialize(String str) {
			if(str.length()<=0)
				return null;
			String[] strArray=str.split(","); 
			TreeNode pHead=new TreeNode(Integer.parseInt(strArray[0]));		
			int[] array1=new int [1];
			array1[0]=0;			
			TreeNode  res=deseiriaImp(pHead,strArray,array1);	
			return res;
	  }
		
	  private TreeNode deseiriaImp(TreeNode node,String[] strArray, int[] array1) {
		    if( strArray[array1[0]].equals("#") || (array1[0]==strArray.length))
		    {		    	
		    	array1[0]++;
		    	return null;
		    }
		        node=new TreeNode(Integer.parseInt(strArray[array1[0]]));
		    	array1[0]++;	    	
		    	node.left=deseiriaImp(node.left,strArray,array1);			    			 
		    	node.right=deseiriaImp(node.right,strArray,array1);	    	
		    	return node;		     		     	    		    		   		    
		}



	public static void main(String[] args)
		{
		TreeNode node1=new TreeNode(1);
		TreeNode node2=new TreeNode(2);
		TreeNode node3=new TreeNode(3);
		TreeNode node4=new TreeNode(4);
		TreeNode node5=new TreeNode(5);
		TreeNode node6=new TreeNode(6);		
	    node1.left= node2;
	    node1.right=node3;    
	    node2.left= node4;
	    node2.right=null ;    
	    node3.left=node5 ;
	    node3.right= node6;   
	    node4.left= null;
	    node4.right=null;
	    node5.left= null;
	    node5.right=null;
	    node6.left= null;
	    node6.right=null ;		   
	    String seriaStr="1,2,4,#,#,#,3,5,#,#,6,#,#";	     
	    new Solution().Deserialize(seriaStr);					 
		}	
} 

     调试结果(调用递归函数后,pHead的值):


     这次结果正确了。在普通函数中直接改变pHead的引用可以,为什么在没有返回值的递归中不行呢?pHead返回的节点值是1,而不是null说明,说明程序在逻辑上是正确的,与是否递归没有关系。在递归函数中直接用deseiriaImp(node.left,strArray,array1),认为下次递归的输入变量node就和上次的node.left关联。在递归遍历树的时候的确是这样,因为树已经存在,节点的子节点已经确定。但是如果node.left等于null的时候,它们将失去关联性,在子递归函数中改变node对上一递归函数的节点没有任何影响。deseiriaImp(node.left,strArray,array1)中的node.left并没有将下次递归中的node与本次node的左子树绑定。正确的方法是:只能显性的赋值,让node.left=deseiriaImp(node.left,strArray,array1),使节点关联起来。递归函数最后将头结点返回。

     

  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值