【发布时间】:2012-07-09 16:23:42
【问题描述】:
假设我根据this post 中的建议定义了一棵树,尽管在我的情况下它是一个向量,但希望这无关紧要(它们是 Programming Clojure 书中的向量):
(def tree [1 [[2 [4] [5]] [3 [6]]]])
应该是这样的:
1
/ \
2 3
/ \ |
4 5 6
现在,我想在不使用任何传统方法(例如队列)的情况下对树进行广度优先遍历,而是专门使用堆栈来传递信息。我知道这不是最简单的路线,但我主要是作为锻炼来做的。同样在这一点上,我不打算返回一个集合(我会在之后作为练习来解决这个问题),而是在我遍历它们时打印出节点。
我目前的解决方案(刚开始使用 Clojure,请客气):
(defn breadth-recur
[queue]
(if (empty? queue)
(println "Done!")
(let [collections (first (filter coll? queue))]
(do
; print out nodes on the current level, they will not be wrapped'
; in a [] vector and thus coll? will return false
(doseq [node queue] (if (not (coll? node)) (println node)))
(recur (reduce conj (first collections) (rest collections)))))))
最后一行没有按预期工作,我不知道如何修复它。我确切地知道我想要什么:我需要剥离每一层向量,然后将结果连接起来传递给 recur。
我看到的问题主要是:
IllegalArgumentException Don't know how to create ISeq from: java.lang.Long
基本上 conj 不喜欢将向量附加到 long 上,如果我将 conj 换成 concat,那么当我是两个项目之一时我会失败连接不是向量。 conj 和 concat 在面对时都失败:
[2 [4] [5] [3 [6]]]
我觉得我在这里遗漏了一个非常基本的操作,它可以在两个位置上对向量和基元都起作用。
有什么建议吗?
编辑 1:
这棵树实际上应该是(感谢 Joost!):
(def tree [1 [2 [4] [5]] [3 [6]]])
但是我们还没有找到广度优先的解决方案。
【问题讨论】:
-
你看过clojure.walk或tree-seq中的函数的来源吗?他们实现了树遍历,你可能会感兴趣。
-
@Gert:我的印象是所有这些都是深度优先的,对吗?我也考虑过拉链,但后来我的大脑开始融化。
-
啊,是的,
clojure.walk进行深度优先遍历;我错过了您帖子中的广度优先要求,哎呀!
标签: algorithm clojure functional-programming