二叉树搜索算法错误

时间:2009-12-05 00:57:57

标签: java search recursion binary-tree

我有一个需要搜索的二叉树。我不是在搜索树的一个特定节点,而是在树的每个节点上搜索有关它们的信息。我现在有一个简单的递归搜索,但每次运行时都会出现堆栈溢出错误。它是一个深度为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对应于根节点,所以我需要检查它是不是 不是父母。 searchNodes的事情是确保我不搜索 同一个节点两次。关于如何做到这一点的任何想法?

编辑:这是整个搜索方法

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)

3 个答案:

答案 0 :(得分:2)

您的数据结构最为奇特。看起来你已经将树扁平化为一组节点。它使你的算法真的很难理解,几乎肯定是个坏主意。

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

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

答案 1 :(得分:0)

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

答案 2 :(得分:0)

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

例如,一些伪代码

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 );
}

如果要为多个蚂蚁触发此代码的多个副本,并且只让一个蚂蚁触摸任何一个节点,则需要多个线程和一个带锁定等的共享数据结构。

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