Java按值传递和递归

Java按值传递和递归,java,algorithm,data-structures,arraylist,Java,Algorithm,Data Structures,Arraylist,我有一个简单的代码,可以打印到树中特定节点的路径。我使用java字符串的实现如下 //using strings public static void getPathS(Node node,String path,int key){ if (node == null) { return; } else if(node.data == key) { System.out.println(path+" "+key);; } getPa

我有一个简单的代码,可以打印到树中特定节点的路径。我使用java字符串的实现如下

//using strings
public static void getPathS(Node node,String path,int key){
    if (node == null) {
        return;
    } else if(node.data == key) {
        System.out.println(path+" "+key);;
    }

    getPathS(node.left,path+" "+node.data,key);
    getPathS(node.right,path+" "+node.data,key);
}
假设下面有一棵树

如果我在3上调用getpath,上面的实现将打印出来

1 34 3 //path from root to the element
如果我使用ArrayList实现相同的方法,如下所示

public static List getPath(Node node, List<Integer> path, int key) { 
    if (node == null) {
        //1 . path = new ArrayList<Integer>();
        path = new ArrayList<Integer>();
        // 2. or tried path.clear()  -- it should clear the path
        //return path;
        return null;
    } else if (node.data == key) {
        path.add(node.data);
        return path;
    }

    path.add(node.data);
    return nonNull(getPath(node.left, path, key), getPath(node.right, path, key));
}

private List nonNull(List path1, List path2) {
    if (path1 != null)
        return path1;
    if(path2 !=null )
        return path2;
    return null;
}

// class Node { Node left, Node right , int data; };
//Code to call getPath  
Node node = new Node(1);
node.left = new Node(2);
node.left.left = new Node(4);
node.right = new Node(34);
node.right.right = new Node(3);
System.out.println(getPath(node, new ArrayList(), 3));
如果我使用
path.clear()
,它只打印最后一个元素,即要搜索的元素


如何确保
ArrayList
在递归中作为字符串工作非努()/<代码>时,不要考虑两个分支的失败。 这里是一个考虑到这种可能性的修正,如果在其子节点中找不到密钥,则会删除当前节点的数据

public static List<Integer> getPath(Node node, List<Integer> path, int key) {
    if (node == null) {
        return null;
    } else if (node.data == key) {
        path.add(node.data);
        return path;
    }
    path.add(node.data);

    // path is unchanged if nothing is found in left children
    if (getPath(node.left, path, key) != null || getPath(node.right, path, key) != null) {
        // found in one branch or the other
        return path;
    }

    // not found in either branch, remove our data
    path.remove(path.size() - 1);
    return null;
}
公共静态列表getPath(节点节点、列表路径、int键){
if(node==null){
返回null;
}else if(node.data==键){
添加(节点数据);
返回路径;
}
添加(节点数据);
//如果在左侧子级中未找到任何内容,则路径将保持不变
if(getPath(node.left,path,key)!=null | | getPath(node.right,path,key)!=null){
//发现于一个分支或另一个分支
返回路径;
}
//在任一分支中都找不到,请删除我们的数据
path.remove(path.size()-1);
返回null;
}
当然,看起来我们在处理不同的列表,但只有一个:第一次作为参数提供的列表。这就是为什么要从中删除数据。你需要清楚你的论点


一个更干净的解决方案,强调只有一个列表

/**
 * Appends to the specified list all keys from {@code node} to the {@link Node} containing the
 * specified {@code key}. If the key is not found in the specified node's children, the list is
 * guaranteed to be unchanged. If the key is found among the children, then the specified list
 * will contain the new elements (in addition to the old ones).
 * 
 * @param node
 *            the node to start at
 * @param path
 *            the current path to append data to
 * @param key
 *            the key to stop at
 * @return true if the key was found among the specified node's children, false otherwise
 */
public static boolean getPath(Node node, List<Integer> path, int key) {
    if (node == null) {
        // leaf reached, and the key was not found
        return false;
    }

    // add data to the path
    path.add(node.data);

    // the OR is lazy here, so we treat everything in the given order
    // if getPath failed on the left children, path is unchanged and used for right children
    if (node.data == key || getPath(node.left, path, key) || getPath(node.right, path, key)) {
        // the key is found in the current node, its left children, or its right children
        return true;
    }

    // not found in either branch, remove our data
    path.remove(path.size() - 1);
    return false;
}
/**
*将从{@code node}到{@link node}包含
*指定的{@code key}。如果在指定节点的子节点中找不到该键,则将显示该列表
*保证不变。如果在子项中找到该键,则指定的列表
*将包含新元素(除旧元素外)。
* 
*@param节点
*要在其上启动的节点
*@param路径
*要将数据附加到的当前路径
*@param-key
*停下来的钥匙
*@如果在指定节点的子节点中找到密钥,则返回true,否则返回false
*/
公共静态布尔getPath(节点、列表路径、int键){
if(node==null){
//叶已到达,但找不到钥匙
返回false;
}
//将数据添加到路径
添加(节点数据);
//手术室在这里很懒,所以我们按给定的顺序处理每件事
//如果getPath在左侧子项上失败,则path将保持不变并用于右侧子项
if(node.data==key | | getPath(node.left,path,key)| | getPath(node.right,path,key)){
//该键位于当前节点、其左侧子节点或其右侧子节点中
返回true;
}
//在任一分支中都找不到,请删除我们的数据
path.remove(path.size()-1);
返回false;
}

请注意,我没有使用
path.remove(node.data)
,因为可能有多个节点包含该数据,第一个节点将被删除,而不是最后一个。

什么是
nonNull(arg1,arg2)
?请检查更新的代码确定谢谢。请发布第一次调用
getPath()
的代码。这里的问题是,我想您正在向同一个列表添加/删除元素。你需要使用某种回溯。几分钟后我会想出一些办法。仅供参考,您的新
nonNull()
方法也会做同样的事情;-)事实上,我想出了一个更好的解决方案(清洁剂),我将在一分钟后发布
/**
 * Appends to the specified list all keys from {@code node} to the {@link Node} containing the
 * specified {@code key}. If the key is not found in the specified node's children, the list is
 * guaranteed to be unchanged. If the key is found among the children, then the specified list
 * will contain the new elements (in addition to the old ones).
 * 
 * @param node
 *            the node to start at
 * @param path
 *            the current path to append data to
 * @param key
 *            the key to stop at
 * @return true if the key was found among the specified node's children, false otherwise
 */
public static boolean getPath(Node node, List<Integer> path, int key) {
    if (node == null) {
        // leaf reached, and the key was not found
        return false;
    }

    // add data to the path
    path.add(node.data);

    // the OR is lazy here, so we treat everything in the given order
    // if getPath failed on the left children, path is unchanged and used for right children
    if (node.data == key || getPath(node.left, path, key) || getPath(node.right, path, key)) {
        // the key is found in the current node, its left children, or its right children
        return true;
    }

    // not found in either branch, remove our data
    path.remove(path.size() - 1);
    return false;
}