【问题标题】:Best algorithm on checking a node in a tree path?检查树路径中节点的最佳算法?
【发布时间】:2012-04-12 07:15:43
【问题描述】:

假设我有这棵树:

           O-ROOT
         /        \
    O-A            O-B
     /          /       \
O-A1        O-B1        O-B2

我想在 C# 中执行此操作:

1. Check every node starting from root (I think the best way is trought recursion?);
2. If I found a node with value = "Hello", return true and STOP the searching function;

你能帮我制定出最好的算法吗?

【问题讨论】:

    标签: c# algorithm path tree


    【解决方案1】:
    bool FindHello(Node node)
    {
        if (node.Content == "Hello")
            return true;
        foreach (Node c in node.Children)
            if (FindHello(c))
                return true;
        return false;
    }
    

    【讨论】:

      【解决方案2】:

      我认为解决您的问题的最佳方法是使用breadth first search。它写起来很简单,并且尽可能有效。

      编辑:像这样:

      public bool Search(TreeNode node, string searchString)
      {
         Queue<Control> q = new Queue<Node>();
         q.Enqueue(node);
         while(!q.empty()) {
           Node current = q.Dequeue();
           foreach(var childNode in node.Children)
             if(childNode.Content.CompareTo(searchString) == 0) {
               return true;
             }
             q.Enqueue(childNode);
           }
         }
         return false;
      }
      

      【讨论】:

      • 在树中搜索深度优先更好 - 没有额外的集合,只有递归(递归是 DFS 方式;)
      • 我的经验告诉我其他方面。 dfs的问题是,对于高大的树,会导致栈溢出。
      • 我也这么认为。仅当您可以确定递归深度在某种程度上已知且足够低 - 并且不会改变时,您才应该使用递归。
      • 为什么你认为 BFS 更好? DFS 也可以在没有递归的情况下实现,并且通常使用更少的内存。
      • @Henrik 在没有递归的情况下实现 DFS 的唯一方法是模拟堆栈,这比简单的 BFS 需要更多的努力。我也不认为它会占用更少的内存。我从事计算机科学竞赛已有 10 多年了,我大部分时间都更喜欢 BFS,这是有充分理由的。
      【解决方案3】:

      递归是正确的,请参阅depth-first 或广度优先搜索算法。由于您没有保留已访问节点的列表,因此对树来说要容易得多。

      public bool Search(TreeNode node, string searchString)
      {
         if(node.Value == searchString) return true;
         foreach(var childNode in node.Children)
           if(Search(childNode, searchString)) return true;
         return false;
      }
      

      【讨论】:

        【解决方案4】:

        Breadth First SearchDepth First Search 是最流行的(除其他外)树搜索技术,因此您可以从那里开始。此外,如果树中的每个节点最多有 2 个节点并且它们以某种方式排序,则可以使用 Binary Search Tree 技术。

        【讨论】:

          【解决方案5】:
          1. 确实,为此绝对使用递归。
          2. 如果您使用递归方法,您可以设置一个(静态)成员变量,如结果,并检查每次迭代是否已设置。如果设置,只需跳出方法(返回)即可停止递归进一步运行。

          【讨论】:

          • 我强烈建议不要使用递归!你不知道,树有多深,如果太深,你会因为递归层级太多而导致堆栈溢出。进行广度优先搜索或深度优先搜索。还可以查看有序、后序和前序遍历技术。由于这可能是一项家庭作业/讲座任务,因此最好查找这些关键字。
          • 这不是家庭作业。我正在为我自己的项目在 C# 上构建一个菜单。是的,它不会有 10000 个项目,但总是更好地将东西优化到项目中:) 为什么不递归?广度优先或深度优先使用它:O
          • BFS/DFS 不一定要用。您可以以迭代方式对两者进行编码。递归是一件漂亮而简洁的事情,但是您必须始终注意 A) 方法调用成本性能(虽然不多)和 B) 您不能无休止地递归。如果你肯定有少于 10000 个项目,你可以节省地使用递归。但是如果你正在编写一个更通用的树遍历库(?)——只是一个例子——你需要考虑树的深度