【问题标题】:DFS algorithm is searching from right to leftDFS算法是从右到左搜索
【发布时间】:2017-02-05 16:07:33
【问题描述】:

我写了一个深度优先搜索算法,但它是从树的右侧向左搜索。我可以从我的代码中看到它为什么这样做,但我无法想出一个解决方案来改变它,以便它从左到右搜索。

public class DFS {

    public LinkedList<Node> search(Node root, Node target) {    
        LinkedList<Node> open = new LinkedList<>();
        LinkedList<Node> closed = new LinkedList<>();

        open.addLast(root);
        while (!open.isEmpty()) {
            Node current = open.removeFirst();
            if (current.equals(target)) {
                closed.addLast(current);
                return closed;
            }
            else {
                ArrayList<Node> children = current.getChildren();
                closed.addLast(current);
                for (Node child : children) {
                    if (!open.contains(child) && !closed.contains(child)) {
                        open.addFirst(child);
                    }
                }
            }
        }
        return null;
    }
}

closed 是按访问顺序排列的节点列表。

Node.getChildren() 按添加顺序返回节点子节点的 ArrayList。

编辑

这里是节点类:

public class Node {

    private ArrayList<Node> children;
    private String name;

    public Node(String name){
        children = new ArrayList<Node>();
        this.name = name;
    }

    public ArrayList<Node> getChildren(){
        return new ArrayList<Node>(children);
    }

    public Node addChild(Node child){
        children.add(child);
        return child;
    }

    public void removeChild(Node child){
        children.remove(child);
    }

    public String getName() {
        return name;
    }

    public boolean equals(Node other){
        return (this.getName().compareTo(other.getName())==0);
    }
}

【问题讨论】:

  • 你为什么要做children.remove(child),尤其是在children的循环期间?
  • 既然你指出来了,我不知道它有什么用!基本上我只是想丢弃那个节点。我现在将编辑我的代码
  • @user2357112 已修复。
  • 我有点困惑:标题提到DepthFS,类名是BFS。哪个是错字?只是为了确定,你想要深度优先还是广度优先?在粗略检查您的代码时,我没有看到来自 closed 的任何 pop,这对于 DFS 来说是不寻常的 - 当然,您会有无法得到答案的分支,需要被丢弃。
  • @AdrianColomitchi 我的错,当我在几分钟后编辑我的问题时,我想我复制并粘贴了我的 BFS 算法。我现在已经修好了。 closed 返回一个正确的 DFS 搜索模式,但它会尽可能沿着树的右侧而不是左侧移动

标签: java search tree depth-first-search


【解决方案1】:

如果你的 DFS 真的依赖方向,反转你的孩子,还是 addFirst 而不是 addLast?

【讨论】:

    【解决方案2】:

    对“如何避免从右到左”问题的简单回答是:

                ArrayList<Node> children = current.getChildren();
                closed.addLast(current);
                // *** Not like this ***
                // for (Node child : children) {
                //    if (!open.contains(child) && !closed.contains(child)) {
                //        open.addFirst(child);
                //    }
                //}
                // **** But like this ****
                for(int i=children.size()-1; i>=0; i-- ) {
                    Node child=children.get(i);
                    if (!open.contains(child) && !closed.contains(child)) {
                        open.addFirst(child);
                    }
                }
                // If you are **absolutely** sure your structure is a 
                // Tree (thus, no cycles) then testing against 
                // open/closed is unnecessary and the code can be simplified: as
                // open.addAll(0, children);
    

    无论如何,您的算法都有缺陷:没有规定可以结束/丢弃树中未能产生结果的下降路径(您永远不会从 closed 中删除)-但这超出了您的问题范围。

    【讨论】:

    • 这很有效,我现在也明白了为什么通过在纸上写一个测试用例。谢谢你。该算法作为伪代码提供给我们,任务要求编写一个测试类,说明是否可以找到到目标节点的路径 - 我认为这是对您指出的内容的保护。我们刚刚开始使用这些搜索算法,因此在这种情况下可能会尽可能简单。
    • 虽然我的回答从“访问顺序”的角度来看是有效的,但请注意,您 closed 列表确实 不 包含从根目录开始的降序路径,但 您访问过的所有节点,直到您找到答案 - 包括失败的分支。如果作业要求您返回实际的“根路径”,您还有工作要做。
    • 我知道这一点,但分配的范围要求打印在目标节点之前访问过的所有节点。感谢您的帮助
    • 啊,好的,搜索的痕迹。在这种情况下,它是正确的。
    【解决方案3】:

    getChildren 有元素 1..n

    然后你有一个“打开”的堆栈,每次执行主循环时你都会从中弹出第一个元素。

    你通过将子元素推到堆栈的前面来填充这个堆栈 (addFirst),然后对于 1..n 你以 n..1 结尾(插入 1,现在是第一个,插入 2,现在是第一,1 是第二,依此类推)。

    从最后一个索引弹出打开,或将子项推送到堆栈的末尾,它应该可以工作,除非 getChildren 没有按照您声称的顺序返回。

    【讨论】:

    • 在编写此 DFS 算法之前,我编写了一个 BFS 算法,其中唯一的区别是您提出的解决方案。从最后一个索引弹出创建 BFS 算法。我已经测试了getChildren(),它确实以正确的顺序返回列表。
    • 是的,你一直在编辑你的问题,代码每次都会改变顺序
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-02
    • 2022-10-30
    • 2018-04-03
    • 1970-01-01
    • 1970-01-01
    • 2015-02-02
    相关资源
    最近更新 更多