(java)DFS遍历中的奇怪列表值
我试图解决一个问题: 打印二叉树从根到叶的所有路径 我编写了以下代码,结果是正确的:(java)DFS遍历中的奇怪列表值,java,arraylist,tree,traversal,microsoft-distributed-file-system,Java,Arraylist,Tree,Traversal,Microsoft Distributed File System,我试图解决一个问题: 打印二叉树从根到叶的所有路径 我编写了以下代码,结果是正确的: public void printPath(TreeNode root) { printDFS(root, new int[1000], 0); } private void printDFS(TreeNode r, int[] path, int idx){ if (r == null) return; path[idx] = r.val; idx++;
public void printPath(TreeNode root) {
printDFS(root, new int[1000], 0);
}
private void printDFS(TreeNode r, int[] path, int idx){
if (r == null) return;
path[idx] = r.val;
idx++;
/* if it's leaf, print path: from root to leaf */
if (r.left == null && r.right == null)
printOnePath(path, idx);
else {
/* go left, go right */
printDFS(r.left, path, idx);
printDFS(r.right, path, idx);
}
}
private void printOnePath(int[] path, int idx) {
for (int i = 0; i < idx; i++) {
System.out.print(path[i] + " ");
}
System.out.println();
}
public void打印路径(TreeNode root){
printDFS(根,新整数[1000],0);
}
私有void printDFS(TreeNode r,int[]路径,int idx){
如果(r==null)返回;
路径[idx]=r.val;
idx++;
/*如果是叶,打印路径:从根到叶*/
if(r.left==null&&r.right==null)
printOnePath(path,idx);
否则{
/*向左走,向右走*/
printDFS(右左,路径,idx);
printDFS(右,路径,idx);
}
}
私有void printOnePath(int[]路径,int idx){
对于(int i=0;i
然而,当我尝试使用ArrayList来存储路径数据而不是 int[]
这种方法是错误的
输出结果真的让我不知所措
public void打印路径(TreeNode root){
printDFS(root,newarraylist(),0);
}
私有void printDFS(TreeNode r,列表路径,int idx){
如果(r==null)返回;
路径添加(r.val);
idx++;
/*如果是叶,打印路径:从根到叶*/
if(r.left==null&&r.right==null)
printOnePath(path,idx);
否则{
/*否则,向左走,向右走*/
printDFS(右左,路径,idx);
printDFS(右,路径,idx);
}
}
私有void printOnePath(列表路径,int-idx){
对于(int i=0;i
例如:
对于二叉树:第一个标准是:(正确)
10 5 3 3
10 5 3 -2
10 5 2 1
10 -3 11
第二个标准是:(错)
10 5 3 3
10 5 3 3
10 5 3 3
10 5 3
我相信初始ArrayList在每个DFS开始时都已设置为空。
为什么即使使用相同的方法,int数组的结果也完全不同
有人知道为什么吗?非常感谢 行:
path[idx] = r.val;
及
它们并不等同
结果是,第一个路径之后的后续路径将添加到列表的末尾。当您打印路径
时,不会看到这些,因为您只打印到idx
元素
我不相信Java中有数组赋值的直接列表等价物
召唤
path.set(idx, r.val);
不起作用,因为Java不会自动增加列表
召唤
path.add(idx, r.val);
由于它将现有元素向右移动,因此也不起作用
如果您想使用列表,我想您必须在打印后将其清除。区别在于
idx
,一个int
,是按值传递的。但是,ArrayList
路径
是一个对象;因此,虽然作为引用的参数是按值传递的,但是path
引用的对象不是按值传递的,而是在递归方法的所有调用中共享的
这意味着在第一个方法中,当您递归调用它时:
printDFS(r.left, path, idx);
printDFS(r.right, path, idx);
在r.left
上调用printDFS
时,假设idx
为3。当递归方法使用idx++
递增idx
时,它们正在递增idx
的新副本。因此,当递归方法最终结束并返回时,该方法使用的idx
的副本仍然是3,因此它将调用printDFS(r.right,path,3)
。这会产生不同,因为您使用idx
设置path[idx]
在第二种方法中,idx
的行为方式相同,但在构建ArrayList
时没有使用它。相反,您将添加到ArrayList
。所以当你打电话的时候
printDFS(r.left, path, idx);
printDFS(r.right, path, idx);
现在,如果在r.left
上调用printDFS
时path
有3个元素,当递归调用结束并返回时,它们已添加到ArrayList
——并且由于此对象在所有递归调用中共享,path
仍将包含递归调用添加到其中的所有元素。因此,与第一个代码示例不同,您调用的printDFS(r.right…
值与调用的printDFS(r.left…
值不同
有几种方法可以解决此问题:
idx
设置数组元素,如另一个答案所示。但是,您需要检查idx
是否是现有元素的索引,如果元素存在,则使用set
;如果idx
等于path.size(),则使用add
printDFS
之前,复制一份path
。这确保了所有递归调用都有自己的数组干净副本。(或在printDFS
的开头复制一份,并使用该副本而不是原始路径;这应确保没有printDFS
修改其调用者的路径
)printDFS
都保留它找到路径的方式。因此,由于printDFS
在数组末尾添加了一个新元素,因此请在返回之前删除数组的最后一个元素。(我相信这会奏效,尽管我还没有测试过它。但是,我一般不推荐这种方法;对于更复杂的递归情况,正确地进行“清理”可能非常困难。)我遵循ajb提到的复制策略(本评论中的选项2)。这是修改后的代码
import apple.laf.JRSUIUtils;
import java.util.ArrayList;
import java.util.List;
/**
* Created by anilwaddi on 8/1/17.
*/
public class DFSTest {
public static void main(String args[]) throws Exception {
DFSTest test = new DFSTest();
test.printDFS();
/*
10 5 3 3
10 5 3 -2
10 5 2 1
10 -3 11
*/
}
TreeNode root;
DFSTest() {
TreeNode node41 = new TreeNode(3, null, null);
TreeNode node42 = new TreeNode(-2, null, null);
TreeNode node43 = new TreeNode(1, null, null);
TreeNode node31 = new TreeNode(3, node41, node42);
TreeNode node32 = new TreeNode(2, node43, null);
TreeNode node33 = new TreeNode(11, null, null);
TreeNode node21 = new TreeNode(5, node31, node32);
TreeNode node22 = new TreeNode(-3, node33, null);
root = new TreeNode(10, node21, node22);
}
public void printDFS() {
printPath(root);
}
public void printPath(TreeNode root) {
printDFS(root, new ArrayList<Integer>());
}
private void printDFS(TreeNode r, List<Integer> path ) {
if (r == null) return;
path.add(r.val);
/* if it's leaf, print path: from root to leaf */
if (r.left == null && r.right == null)
printOnePath(path );
else {
/* otherwise: go left, go right */
List<Integer> newPathLeft = new ArrayList<>();
newPathLeft.addAll(path);
printDFS(r.left, newPathLeft);
List<Integer> newPathRight = new ArrayList<>();
newPathRight.addAll(path);
printDFS(r.right, newPathRight);
}
}
private void printOnePath(List<Integer> path ) {
for (int i = 0; i < path.size(); i++) {
System.out.print(path.get(i) + " ");
}
System.out.println();
}
private class TreeNode {
TreeNode left;
TreeNode right;
Integer val;
TreeNode(Integer val) {
this.val = val;
}
TreeNode(Integer val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
}
导入apple.laf.jrsuitils;
导入java.util.ArrayList;
导入java.util.List;
/**
*anilwaddi于2017年8月1日创建。
*/
公共类测试{
公共静态真空总管(
printDFS(r.left, path, idx);
printDFS(r.right, path, idx);
import apple.laf.JRSUIUtils;
import java.util.ArrayList;
import java.util.List;
/**
* Created by anilwaddi on 8/1/17.
*/
public class DFSTest {
public static void main(String args[]) throws Exception {
DFSTest test = new DFSTest();
test.printDFS();
/*
10 5 3 3
10 5 3 -2
10 5 2 1
10 -3 11
*/
}
TreeNode root;
DFSTest() {
TreeNode node41 = new TreeNode(3, null, null);
TreeNode node42 = new TreeNode(-2, null, null);
TreeNode node43 = new TreeNode(1, null, null);
TreeNode node31 = new TreeNode(3, node41, node42);
TreeNode node32 = new TreeNode(2, node43, null);
TreeNode node33 = new TreeNode(11, null, null);
TreeNode node21 = new TreeNode(5, node31, node32);
TreeNode node22 = new TreeNode(-3, node33, null);
root = new TreeNode(10, node21, node22);
}
public void printDFS() {
printPath(root);
}
public void printPath(TreeNode root) {
printDFS(root, new ArrayList<Integer>());
}
private void printDFS(TreeNode r, List<Integer> path ) {
if (r == null) return;
path.add(r.val);
/* if it's leaf, print path: from root to leaf */
if (r.left == null && r.right == null)
printOnePath(path );
else {
/* otherwise: go left, go right */
List<Integer> newPathLeft = new ArrayList<>();
newPathLeft.addAll(path);
printDFS(r.left, newPathLeft);
List<Integer> newPathRight = new ArrayList<>();
newPathRight.addAll(path);
printDFS(r.right, newPathRight);
}
}
private void printOnePath(List<Integer> path ) {
for (int i = 0; i < path.size(); i++) {
System.out.print(path.get(i) + " ");
}
System.out.println();
}
private class TreeNode {
TreeNode left;
TreeNode right;
Integer val;
TreeNode(Integer val) {
this.val = val;
}
TreeNode(Integer val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
}