相当于Java中的传递引用,用于null传递指针

时间:2013-03-08 07:08:10

标签: java pass-by-reference

我对将可能包含null的对象传递给其他方法的最佳方法有疑问。如果传递的对象为null,则另一个方法将创建一个新实例。我的问题是如何允许第二种方法修改origina初始传递的null对象指针。基本上,我在从文件读取BST并制作树时遇到了这个问题。我认为使用相同的例子来解释这个问题会更加明显:

在下面的代码中,我正在从存储在队列中的所有值中读取并构建BST。 Queue值是我从另一个方法读取的树的按顺序遍历。

    TreeNode root2;
public void readBST(Queue<Integer> input){
    if (input==null || input.isEmpty()) return;     
    int i=input.poll();
    root2 = new TreeNode(i);
    readBSTHelper(root2.leftChild , input, Integer.MIN_VALUE , i-1);
    readBSTHelper(root2.rightChild, input, i+1, Integer.MAX_VALUE);
}

private void readBSTHelper(TreeNode curr, Queue<Integer> input, int min, int max){
    if (input==null && input.isEmpty()) return;
    int i = input.peek();
    if (i>=min && i<=max){
        input.poll();
        curr = new TreeNode(i);
        readBSTHelper(curr.leftChild, input, min, i-1);
        readBSTHelper(curr.rightChild,input, i+1, max);
    }
}

但是,我遇到的问题是,在创建root2时,leftChildrightChildnull。事实上,TreeNode(i)制作TreeNode data=ileftChildrightChild等于null。当我通过readBSTHelper调用root2.leftChild时,它会传递null指针。由于它是null指针,因此null指针的副本将传递给readBSTHelper。因此,readBSTHelper的结果将丢失,并且永远不会返回/分配给真实的root2.leftChild。我们可以通过传递原始指针的引用来防止C ++中出现这样的问题。我能够通过修改代码来暂时解决问题:

    TreeNode root2;
public void readBST(Queue<Integer> input){
    if (input==null || input.isEmpty()) return;     
    int i=input.poll();
    root2 = new TreeNode(i);
    readBSTHelper(root2, "left", input, Integer.MIN_VALUE , i-1);
    readBSTHelper(root2, "right", input, i+1, Integer.MAX_VALUE);
}
private void readBSTHelper(TreeNode curr, String side, Queue<Integer> input, int min, int max){
    if (input.isEmpty()) return;
    int i = input.peek();
    if (i>=min && i<=max){
        input.poll();
        if (side.equals("left")) {
            curr.leftChild = new TreeNode(i);
            readBSTHelper(curr.leftChild,"left", input, min, i-1);
            readBSTHelper(curr.leftChild, "right", input, i+1, max);
        } else {
            curr.rightChild = new TreeNode(i);
            readBSTHelper(curr.rightChild,"left", input, min, i-1);
            readBSTHelper(curr.rightChild, "right", input, i+1, max);
        }

    }
}

但这段代码看起来很难看。关于如何使第一个代码工作的任何建议?

1 个答案:

答案 0 :(得分:2)

选项1:包装

class NodeWrapper
{
  TreeNode node;
}

class TreeNode
{
  ...
  TreeNode(int num)
  {
    leftChild = new NodeWrapper();
    rightChild = new NodeWrapper();
    ...
  }
  NodeWrapper leftChild, rightChild;
}

void readBSTHelper(NodeWrapper curr, Queue<Integer> input, int min, int max)
{
  ...
}

选项2:在构造函数中初始化子项

我建议有一个专门用于此目的的单独构造函数(不在下面),否则你的insert函数会错误地创建子代。

class TreeNode
{
  ...
  TreeNode()
  {
    val = null;
  }
  TreeNode(int num)
  {
    init(num);
  }
  init(int num)
  {
    leftChild = new TreeNode();
    rightChild = new TreeNode();
    val == num;
  }
  Integer val;
}

public void readBST(Queue<Integer> input){
    if (input==null || input.isEmpty()) return;     
    int i=input.poll();
    root2 = new TreeNode(i);
    if (!readBSTHelper(root2.leftChild , input, Integer.MIN_VALUE , i-1))
      root2.leftChild = null; // delete child if not populated
    if (!readBSTHelper(root2.rightChild, input, i+1, Integer.MAX_VALUE))
      root2.rightChild = null; // delete child if not populated
}

boolean readBSTHelper(TreeNode curr, Queue<Integer> input, int min, int max){
    if (input==null && input.isEmpty()) return false;
    int i = input.peek();
    if (i>=min && i<=max){
        input.poll();
        curr.init(i);
        if (!readBSTHelper(curr.leftChild, input, min, i-1))
          curr.leftChild = null;
        if (!readBSTHelper(curr.rightChild, input, i+1, max))
          curr.rightChild = null;
        return true;
    }
    return false;
}