递归搜索算法有哪些替代方案?

时间:2011-12-29 16:29:54

标签: c# linq recursion

我正在研究我一直在研究的深度搜索算法的替代方案。我的代码在这里发布有点太长了,但我写了一个简化版本来捕获重要的方面。首先,我创建了一个对象,我将其称为“BranchNode”,它包含一些值以及一组其他“BranchNode”对象。

class BranchNode : IComparable<BranchNode>
{
    public BranchNode(int depth, int parentValue, Random rnd)
    {
        _nodeDelta = rnd.Next(-100, 100);
        _depth = depth + 1;
        leafValue = parentValue + _nodeDelta;

        if (depth < 10)
        {
            int children = rnd.Next(1, 10);
            branchNodes = new BranchNode[children];
            for (int i = 0; i < children; i++)
            {
                branchNodes[i] = new BranchNode(_depth, leafValue, rnd);
            }
        }
    }

    public int CompareTo(BranchNode other)
    {
        return other.leafValue.CompareTo(this.leafValue);
    }


    private int _nodeDelta;
    public BranchNode[] branchNodes;
    private int _depth;
    public int leafValue;


}

在我的实际程序中,我从其他地方获取数据......但是对于这个例子,我只是将一个Random对象的实例传递给我用来为每个BranchNode生成值的行。 ..我也手动创建10的深度,而我的实际数据将有任意代数。

作为对目标的快速解释,_nodeDelta包含分配给每个BranchNode的值。每个实例还维护一个leafValue,它等于当前BranchNode的_nodeDelta与其所有祖先的_nodeDeltas相加。我试图找到没有子节点的BranchNode的最大leafValue。

目前,我递归地遍历heirarchy搜索其子BranchNodes数组为null的BranchNodes(a.k.a:'无子'BranchNode),然后将它的leafValue与当前最高leafValue的leafValue进行比较。如果它更大,它将成为基准,并继续搜索,直到它查看所有BranchNodes。

我可以发布我的递归搜索算法,如果它有帮助,但它非常标准,并且工作正常。正如预期的那样,我的问题是,对于较大的heirarchies,我的算法需要很长时间来横向于内部结构。

我想知道我是否有任何其他可以选择的选项可能会产生更快的结果...具体来说,我一直试图绕着linq包围,但我甚至不确定它是否已构建做我正在寻找的,或者它是否更快。还有其他我应该研究的事情吗?

4 个答案:

答案 0 :(得分:1)

也许您想要研究另一种数据索引结构:Here

它总是取决于您对数据所做的工作,但如果您在存储分层表单的每个元素上分配唯一ID,并创建存储的索引,那么优化将比微观更有意义。 - 优化你所做的部分。

此外,这也为搜索算法提供了一个非常不同的范例,它不使用递归,而是为ID和可能的索引增加内存的成本。

答案 1 :(得分:1)

如果您必须访问所有叶子节点,则无法加速搜索:无论如何,它都将通过所有节点。为加速树搜索而采用的典型技巧是以一种特殊的方式组织它们,简化了对树的搜索。例如,通过构建二叉搜索树,您可以进行搜索O(Log(N))。您还可以在非叶节点中存储一些有用的值,稍后您可以从中构建搜索查询的答案。

例如,您可以决定将_bestLeaf“指向”存储到具有当前子树下所有叶子的最高_nodeDelta的叶子。如果您这样做,您的搜索将成为O(1)查找。但是,您的插入和删除会变得更加昂贵,因为您需要在使用新Log-b(N)返回root的路上更新最多_bestLeaf项(b是分支因素你的树。)

答案 2 :(得分:1)

我认为你应该考虑的第一件事就是离开N-Tree并转向二元搜索树。

这意味着所有节点只有2个孩子,更大的孩子和更小的孩子。

从那里开始,我会考虑平衡你的搜索树与红黑树或AVL之类的东西。这样,搜索树就是O(log n)。

以下是一些可以帮助您入门的链接:

http://en.wikipedia.org/wiki/Binary_search_tree http://en.wikipedia.org/wiki/AVL_tree http://en.wikipedia.org/wiki/Red-black_tree

现在,如果您已准备好让每个节点都能够拥有N个子节点,那么您应该注意以下几点:

  1. 考虑订购子节点,以便快速确定哪个叶子编号最高。这样,当您进入一个新节点时,您可以检查一个子节点并快速确定是否值得以递归方式检查它的子节点。
  2. 考虑一下您可以尽可能快地从搜索中尽可能多地消除节点或尽可能早地中断递归调用的方法。使用二叉搜索树,您可以通过始终只查看更大的子项来轻松找到最大的叶节点。如果树是平衡的,这可以消除N-log(n)个孩子。
  3. 考虑插入和删除节点。如果你在这里花更多的时间,你可以节省更多的时间

答案 3 :(得分:0)

正如其他人所提到的,不同的数据结构可能就是您想要的。

如果需要保持数据结构相同,可以将递归展开为循环。虽然这种方法可能会快一点,但速度不会快几个数量级,但可能会占用更少的内存。