搜索项

时间:2018-02-11 17:19:45

标签: java arrays recursion

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

我无法弄清楚如何实现这一目标。我能想到的两个选项是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);
            }
        }
    }

这种情况有意义吗?如果是这样,有什么想法?它甚至可能吗? (我试过搜索,但我的所有查询都没有用)

提前感谢您的帮助。干杯!

2 个答案:

答案 0 :(得分:1)

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

我不明白你的意思&#34;如果可以在不穿越整棵树的情况下进行水平顺序遍历&#34;。如果您的树T没有秩序感,那么必须遍历整个树,因为目标T可能在任何地方。这正是你想要做的,不是吗?

将此问题视为两个相互递归的函数可能在概念上有所帮助。一个函数可以称为SearchT,另一个函数可以称为SearchArrayListT。 SearchT检查T是否是&#34;目标&#34; T.如果没有,它在T的ArrayList字段上调用SearchArrayListT。

如果传入的ArrayList为空,则SearchArrayListT产生&#34; false&#34; (即你表示没有找到目标的事实。)否则,SearchArrayListT在ArrayList的每个元素上调用SearchT,在每个元素之后检查是否&#34; true&#34;返回(或者您表示找到目标的事实)。这实际上是深度优先搜索,但您应该得到相同的结果。您可以看到如何在维基百科页面上为他们进行广度优先搜索:https://en.wikipedia.org/wiki/Breadth-first_search

特别针对您的问题,看起来您正在寻找&#34; root&#34;的路径。进入&#34;目标&#34; T,所以在这种相互递归期间,你想要通过迄今为止的路径,然后追加到目前为止的路径#34;沿着递归。更具体地说,SearchT将在pathSoFar中追加take,然后使用附加了&#34; T&#34;的pathSoFar调用SearchArrayListT。 SearchT也作为一个论点。像这样:

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)

答案 1 :(得分:0)

如果您尝试递归查找图表中的项目,可以使用depth first search

在遍历期间,您需要标记访问过的节点,这样您就不会在循环中继续访问它们。只有在尚未访问过节点的情况下,您才会访问节点的子节点。

这是一个使用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 +
                '}';
    }
}

如果你运行这个类(它只有一个main方法用于测试目的),你会看到这个输出:

true
Node{value=3, children=null}
false

此算法不会告诉您最短路径。它只会告诉您,如果值在图表中以及在哪个节点中。

如果您尝试在有向图中找到源节点的最短路径,请更好地使用Breadth-first search