Java按值传递和递归
我有一个简单的代码,可以打印到树中特定节点的路径。我使用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
//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;
}