Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/360.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 搜索项目的嵌套列表_Java_Arrays_Recursion - Fatal编程技术网

Java 搜索项目的嵌套列表

Java 搜索项目的嵌套列表,java,arrays,recursion,Java,Arrays,Recursion,假设我有一个类型为T的对象,其中一个字段包含一个ArrayList,该ArrayList保存我将调用list的类型为T的对象。我还有另一个类型为T的对象,我称之为goal。我正在努力寻找目标。要做到这一点,我想首先遍历列表,看看目标是否存在。如果是,我想返回原始对象。如果不是,那么我想逐个对象地查看列表,并检查每个列表中的目标(如果找到,则返回对象)。我希望递归地继续此搜索,直到找到匹配项 我想不出如何做到这一点。我能想到的两个选项是while循环和递归。然而,当我查看各种列表时,我必须在不同的

假设我有一个类型为T的对象,其中一个字段包含一个ArrayList,该ArrayList保存我将调用list的类型为T的对象。我还有另一个类型为T的对象,我称之为goal。我正在努力寻找目标。要做到这一点,我想首先遍历列表,看看目标是否存在。如果是,我想返回原始对象。如果不是,那么我想逐个对象地查看列表,并检查每个列表中的目标(如果找到,则返回对象)。我希望递归地继续此搜索,直到找到匹配项

我想不出如何做到这一点。我能想到的两个选项是while循环和递归。然而,当我查看各种列表时,我必须在不同的级别之间来回摆动,我不知道如何做到这一点

我的另一个想法是,我想做的事情与树的水平阶横截是一样的。然而,到目前为止,我只了解了二叉树,我不知道如何或是否可以将其转换为一棵树,更不用说,如果可以在不遍历整棵树的情况下执行级别顺序遍历的话

下面,请参阅到目前为止我编写的代码。这将只检查第一个列表是否匹配,而不深入我需要的内容

/**
     * Searches for the shortest path between start and end points in the graph.
     * @param start
     * @param end
     * @return a list of data, starting with start and ending with end, that gives the path through
     * the graph, or null if no such path is found.  
     */
    public List<T> shortestPath(T startLabel, T endLabel){
        List<T> list = new ArrayList<>();
        list.add(startLabel);
        while(true){
            List<T> successors = successorList(startLabel);
            if (containsMatch(successors, endLabel)) {
                findMatch(successors, endLabel);
            }
        }
    }
/**
*搜索图形中起点和终点之间的最短路径。
*@param start
*@param-end
*@返回一个数据列表,从开始到结束,给出通过的路径
*图形,如果找不到这样的路径,则为null。
*/
公共列表最短路径(T标签,T endLabel){
列表=新的ArrayList();
列表。添加(标签);
while(true){
列表继承者=成功者列表(STARTABEL);
if(containsMatch(后继者,endLabel)){
findMatch(后继者、endLabel);
}
}
}
这种情况有意义吗?如果是,有什么想法?有可能吗? (我试着搜索,但我所有的查询结果都没有任何用处)


提前感谢您的帮助。干杯

T听起来确实像是一棵树,但这仅限于对于其ArrayList中的每个T(以及每个ArrayList中的每个T等),所有T都是唯一的。否则,当它不是一棵树时,像树一样遍历它可能会导致无限循环

我不明白你所说的“如果有可能在不遍历整棵树的情况下进行级别顺序遍历”是什么意思。如果你的树T没有秩序感,那么你必须遍历整棵树,因为目标T可能在任何地方。这正是你想做的,不是吗

将此问题看作两个相互递归的函数可能在概念上有所帮助。一个函数可以称为SearchT,另一个函数可以称为searchArrayList。SearchT检查T是否为“目标”T。如果不是,则在T的ArrayList字段上调用searchArraylist

如果传入的ArrayList为空,则SearchArrayList会生成“false”(即表示未找到目标的事实)。否则,SearchArrayList会在ArrayList的每个元素上调用SearchT,在每个元素之后检查是否返回“true”(或表示已找到目标的事实)。这实际上是一个深度优先搜索,但是您应该得到相同的结果。你可以在维基百科页面上看到如何进行广度优先搜索:

特别是对于你的问题,看起来你正在寻找从“根”T到“目标”T的路径,所以在这个相互递归过程中,你希望通过“到目前为止的路径”,并沿着递归附加到“到目前为止的路径”。更具体地说,SearchT将在pathSoFar中附加take,然后调用searchArrayList,其中pathSoFar附加SearchT也作为参数接收的“T”。大概是这样的:

SearchT(T t, List<T> pathSoFar) //append t to pathSoFar, check if 
//t is the goal; if it is not call SearchArrayListT(t.list, pathSoFar.add(t)); 

SearchArrayListT(ArrayList<T>, List<T> pathSoFar)
SearchT(T,List pathSoFar)//将T附加到pathSoFar,检查是否
//t是目标;如果不是,则调用searchArrayList(t.list,pathSoFar.add(t));
SearchArrayList(ArrayList,列表路径)

如果您试图递归地在图形中查找项目,则可以使用

在遍历过程中,您需要标记已访问的节点,以便不在循环中继续访问它们。只有在尚未访问节点的子节点时,才会访问这些子节点

下面是一个使用DFS的简单Java实现,它递归地搜索树中的值,然后捕获节点(如果找到)

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class TreeSearch<T> {

    private final Set<T> marked = new HashSet<>();

    private boolean found;

    private Node<T> foundNode;

    public TreeSearch(Node<T> node, T s) {
        dfs(node, s);
    }

    private void dfs(Node<T> node, T s) {
        if(node.value.equals(s)) {
            found = true;
            foundNode = node;
        }
        marked.add(node.value);
        if(node.children != null) {
            for (Node<T> child : node.children) {
                if (!marked.contains(child.value)) {
                    dfs(child, s);
                }
            }
        }
    }

    public boolean isFound() {
        return found;
    }

    public Node<T> getFoundNode() {
        return foundNode;
    }

    public static void main(String[] args) {
        Node<Integer> root = new Node<>(0);
        Node<Integer> n1 = new Node<>(1);
        Node<Integer> n2 = new Node<>(2);
        root.add(n1);
        root.add(n2);
        n2.add(n1);
        Node<Integer> n3 = new Node<>(3);
        n2.add(n3);

        TreeSearch<Integer> search = new TreeSearch<>(root, 3);
        assert search.isFound();
        System.out.println(search.isFound()); // Expects true
        System.out.println(search.getFoundNode());

        TreeSearch<Integer> searchFail = new TreeSearch<>(root, 4);
        assert !searchFail.isFound();
        System.out.println(searchFail.isFound()); // Expects false
    }

}

class Node<T> {

    T value;

    List<Node<T>> children;

    public Node(T value) {
        this.value = value;
    }

    public void add(Node<T> child) {
        if(children == null) {
            children = new ArrayList<>();
        }
        children.add(child);
    }

    @Override
    public String toString() {
        return "Node{" +
                "value=" + value +
                ", children=" + children +
                '}';
    }
}
此算法不会告诉您最短路径。它只会告诉您,图中是否有值,以及在哪个节点中


如果您试图在有向图中找到源节点的最短路径,最好使用。

您的场景有一定的意义。您应该将数据描述为“图形”,而不是像代码所说的列表或其他任何东西。这会更有意义。你有一个图表,你要寻找的是最短路径。说吧。(就像下面的第一个答案一样,一开始我还以为你有一棵树。)
我试着搜索
最短路径问题:@markspace这正是问题所在!我试着把它分解成一个更小的问题,并考虑到一个具体的策略,所以我不仅仅是发布我的家庭作业,但也许这不是最好的方法——我真的不知道。非常感谢你的建议!深度优先的问题是,我们必须检查每条路径以确定最短路径。广度不是更有效吗?此外,如果两个项目在彼此的列表中,我们可能会遇到一个无限循环。我一定会查看维基链接。谢谢你是对的,它会更有效,我只是发现深度搜索方法更容易递归实现(因此更容易解释)。至于碰到无限循环的可能性,那么我们肯定不会使用树,您需要做的是跟踪图中的节点何时被访问。在四处搜索时,我发现了一个答案,Java代码就是这样做的
true
Node{value=3, children=null}
false