Java 搜索项目的嵌套列表
假设我有一个类型为T的对象,其中一个字段包含一个ArrayList,该ArrayList保存我将调用list的类型为T的对象。我还有另一个类型为T的对象,我称之为goal。我正在努力寻找目标。要做到这一点,我想首先遍历列表,看看目标是否存在。如果是,我想返回原始对象。如果不是,那么我想逐个对象地查看列表,并检查每个列表中的目标(如果找到,则返回对象)。我希望递归地继续此搜索,直到找到匹配项 我想不出如何做到这一点。我能想到的两个选项是while循环和递归。然而,当我查看各种列表时,我必须在不同的级别之间来回摆动,我不知道如何做到这一点 我的另一个想法是,我想做的事情与树的水平阶横截是一样的。然而,到目前为止,我只了解了二叉树,我不知道如何或是否可以将其转换为一棵树,更不用说,如果可以在不遍历整棵树的情况下执行级别顺序遍历的话 下面,请参阅到目前为止我编写的代码。这将只检查第一个列表是否匹配,而不深入我需要的内容Java 搜索项目的嵌套列表,java,arrays,recursion,Java,Arrays,Recursion,假设我有一个类型为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