【问题标题】:Binary tree search algorithm errors二叉树搜索算法错误
【发布时间】:2010-12-23 11:12:28
【问题描述】:

我有一个需要搜索的二叉树。我不是在搜索树的一个特定节点,而是搜索树的每个节点以获取有关它们的信息。我现在有一个简单的递归搜索,但每次运行时都会出现堆栈溢出错误。它是一棵深度为 7 的完整二叉树...

if (curDepth < 6 && !searchedNodes[curID * 2]) 
 depthSearch(curNode.getRight());
if (curDepth < 6 && !searchedNodes[curID * 2 + 1]) 
        depthSearch(curNode.getLeft());
if (curID != 1 && !searchedNodes[(int) (curID / 2)]) 
 depthSearch(curNode.getParent());

curID == 1 对应根节点,所以我需要检查它是 不是父母。 searchedNodes 是为了确保我不搜索 同一个节点两次。关于如何做到这一点的任何想法?

编辑:这是整个搜索方法

public void depthSearch(AntTree curNode) {
        boolean[] searchedNodes = new boolean[128];
        if (curNode == null)
            return;
        int curID = curNode.getID();
        searchedNodes[curID] = true;
        if (curNode.getFood() > 0) {
            AntScript.foodLocs[curID] = 1;
        } else {
            Ant6Script.foodLocs[curID] = 0;
        }
        Ant[] ants = curNode.getAnts();
        boolean containsWorker = false, containsSoldier = false;
        if (ants != null) {
            for (int i = 0; i < ants.length; i++) {
                if (ants[i].type().equals("Worker")
                && ants[i].teamID() != AntScript.myTeamID) {
                    containsWorker = true;
                } else if (ants[i].type().equals("Soldier")
                && ants[i].teamID() != AntScript.myTeamID) {
                    containsSoldier = true;
                } else if (ants[i].type().equals("Queen")
                && ants[i].teamID() != AntScript.myTeamID) {
                    AntScript.enemyQueenLoc = curID;
                }
            }
        }
        if (containsWorker)
            AntScript.enemyWorkerLocs[curID] = 1;
        else
            AntScript.enemyWorkerLocs[curID] = 0;
        if (containsSoldier)
            AntScript.enemySoldierLocs[curID] = 1;
        else
            AntScript.enemySoldierLocs[curID] = 0;
        AntScript.viewedNodeLocs[curID] = 1;
        int curDepth = (int) (Math.log(curID) / Math.log(2));
        if (AntScript.viewedNodeLocs[(int) (curID / 2)] == 0
        || (curDepth < 6 && AntScript.viewedNodeLocs[curID * 2 + 1] == 0)
        || (curDepth < 6 && AntScript.viewedNodeLocs[curID * 2] == 0)) {
            if (curDepth < 6
            && AntScript.viewedNodeLocs[curID * 2] == 0
            && !searchedNodes[curID * 2]) {
                depthSearch(curNode.getLeft());
            }
            if (curDepth < 6
            && AntScript.viewedNodeLocs[curID * 2 + 1] == 0
            && !searchedNodes[curID * 2 + 1]) {
                depthSearch(curNode.getRight());
            }
            if (curID != 1
            && AntScript.viewedNodeLocs[(int) (curID / 2)] == 0
            && !searchedNodes[(int) (curID / 2)]) {
                depthSearch(curNode.getParent());
            }
        } else {
            if (curDepth < 6 && !searchedNodes[curID * 2]) {
                depthSearch(curNode.getRight());
            }
            if (curDepth < 6 && !searchedNodes[curID * 2 + 1]) {
                depthSearch(curNode.getLeft());
            }
            if (curID != 1 && !searchedNodes[(int) (curID / 2)]) {
                depthSearch(curNode.getParent());
            }
        }
    }

viewedNodeLocs 数组的目的是因为我有很多蚂蚁在板上执行来自不同节点的搜索,并且最好通过一个以前没有搜索过的节点进行搜索而不是一个已经搜索过的节点。我不能只进行一次大搜索然后完成,因为我对下一个节点的请求应该在来自一只蚂蚁的 13 次请求后返回 null(这整件事来自我正在为游戏编程的蚂蚁 AI)

【问题讨论】:

  • 信息不足。发布整个递归搜索例程。
  • 没有对您实际尝试做的事情的描述使得很难评估您所写的内容。对于一个相对简单的问题,这看起来非常复杂,并且有一些明显的错误。最重要的是,每次递归调用都会创建自己的 searchedNodes 副本并设置一个元素。再往下的测试只查看当前调用的 searchedNodes 并且看不到其他调用设置的任何值。你能发布目标的描述吗?

标签: java search recursion binary-tree


【解决方案1】:

您可以使用树遍历技术来获取有关所有节点的信息。在这里检查 http://en.wikipedia.org/wiki/Pre-order_traversal.

【讨论】:

    【解决方案2】:

    你需要遍历,而不是搜索。

    例如,一些伪代码

    void PrintTree( TreeNode node ){
        if( node == null ) return;
        if( node.Left != null ) PrintTree( node.Left );
        if( node.Right != null ) PrintTree( node.Right );
        Console.Printline( node.Value );
    }
    

    如果您想为多个蚂蚁触发此代码的多个副本,并且只让一个蚂蚁接触任何单个节点,您将需要多个线程和一个具有锁定等功能的共享数据结构。

    现在最好只共享一个“地图”数据结构,每个数据结构都可以通过执行一次遍历来获取对您构建的数据结构的引用。毕竟一棵深度为 7 的树无论如何只会有 128 个节点,所以它没有太多的内存或时间来遍历。如果需要,您可以随时改进它,但至少先让它发挥作用。

    【讨论】:

    • 当你以 'printTree(TreeNode);' 的形式编写树遍历算法时,我觉得很奇怪而不是 'treeNode.print();'甚至'tree.print();'
    【解决方案3】:

    你的数据结构是最奇特的。看起来您已将树展平为节点数组。这让你的算法很难理解,而且几乎可以肯定是个坏主意。

    话虽如此,我怀疑问题与每个对 depthSearch 的递归调用都会分配一个新的 searchedNodes 数组有关。就像我说的,你的算法……很难理解。

    我建议您以传统方式表示您的二叉树,每个节点都有一个“左”和“右”指针。然后按照维基百科文章中描述的方式实现遍历。更好的是,看看 Java Collections 框架,看看现有的 List/Set/Map 实现之一是否符合您的要求。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-12-05
      • 1970-01-01
      • 1970-01-01
      • 2017-06-12
      • 1970-01-01
      • 2019-04-15
      • 2016-12-04
      相关资源
      最近更新 更多