Scheme:递归广度第一个树遍历

时间:2010-05-03 03:08:08

标签: scheme racket

我正在试着弄清楚如何在方案中实现广度优先树遍历。我用Java和C ++完成了它。如果我有代码,我会发布它,但我不确定如何开始。

鉴于下面的树定义,如何使用递归实现广度优先搜索?

(define tree1 '( A ( B (C () ()) (D () ()) ) (E (F () ()) (G () ())) )) 

3 个答案:

答案 0 :(得分:2)

我敢打赌当你用其他语言执行此操作时,你使用了dfs的堆栈和bfs的队列。当您进行深度优先搜索时,您基本上使用堆栈来决定下一个要探索的节点,并且递归会为您提供一个函数调用堆栈,因此很容易将两者如何相互镜像。通过广度优先搜索,问题就变成了,如何递归遍历队列?

现在回想一下,你可以迭代地做任何事情,你可以递归地做。您可以写“当x< 10:x + = 1”时,您可以写

(define (my-loop x)
  (if (< x 10)
      (my-loop (+ x 1))
      ... ;; your base case
      ))

然后突然你以递归方式进行迭代。大。

所以我们有这个队列。我们把事情放在一边,把事情从另一端拿走。就像我们在上面的循环中传递循环控制变量x一样,你必须明确地传递队列。在下一个“迭代”中,现在变为下一个递归级别,您将希望在队列中放置一些新子节点,并且下一次递归将使一个子节点离队列的另一端,或者停止(返回) )如果没有更多的孩子。

现在调用堆栈不再镜像树中的位置,因此很难看出为什么递归会更好或更直观,但它始终是可能的。

希望有所帮助,
GREM

答案 1 :(得分:1)

0)这是家庭作业吗?如果是这样,请停止阅读:)。

BFS算法:如果队列为空,请放弃。否则,将队列分成第一个并保留,检查第一个是否是您想要的队列,否则重复使用包含剩余元素和所有可到达队列的队列。

当然,我可以在Scheme中“说”同一句话:

#lang scheme

(define (bfs pred queue)
  (match queue
    [empty #f]
    [(cons elt queue-rest) 
     (or (pred elt)
         (bfs pred (append queue-rest (remove* queue-rest (reachable-from elt)))))]))

1)完全未经测试,几乎肯定是错误的(尽管不是在测量理论意义上:))

2)你需要自己的图表和图形表示。 “可达-从”

3)列表不是一个很好的队列实现。

答案 2 :(得分:0)

你可以这样做: 有一个递归的辅助函数,它转到深度为n,并用一行连接元素......输出将是一个列表,其中包含深度为n的树的所有元素。

(defun findAtN (tree n)
(cond ((equal tree nil) nil)
      ((equal (n 0)     (car tree))
      (t                (append (findAtN (cadr tree) (- n 1))
                                (findAtN (caddr tree) (- n 1))))))

然后是第二个增加深度的函数,搜索给定节点的每个级别。

(defun ContainsElt (tree Elt n)
(cond ((equal (findAtN tree n) nil)   nil)
      ((member Elt (findAtN tree n))  true)
      (t                              (ContainsElt tree Elt (+ n 1)))))

这是未经测试的,可能会根据您的lisp参数/方言略有不同,以及如果您想要做的不仅仅是测试一个项目是否在树中,但也许它有助于一个想法如何做到这一点。