使用clojure.zip进行Postorder树遍历以编辑节点
我有一个用嵌套向量表示的树。我想对树的使用clojure.zip进行Postorder树遍历以编辑节点,clojure,tree,traversal,zipper,Clojure,Tree,Traversal,Zipper,我有一个用嵌套向量表示的树。我想对树的索引进行一个泛化,显示每个节点的索引,如下所示 (visit 42); => [0 42] (visit [6 7]); => [0 ; [[0 6] ; [1 7]]] 天真的实现将直接使用clojure.zip() 但是使用clojure.zip/next重复执行一个前序遍历,在这种情况下会产生一个无限循环(未访问的节点将无限地连接到[:found]向量中)。另一种
索引进行一个泛化,显示每个节点的索引,如下所示
(visit 42); => [0 42]
(visit [6 7]); => [0
; [[0 6]
; [1 7]]]
天真的实现将直接使用clojure.zip()
但是使用clojure.zip/next
重复执行一个前序遍历,在这种情况下会产生一个无限循环(未访问的节点将无限地连接到[:found]
向量中)。另一种方法是使用clojure.walk/postwark
,但它不提供结构信息,例如索引
您将如何实现这一点?是否有一个zip的后序下一步
可以立即解决问题?我不确定是否理解您的意图,但示例向我表明,分配给节点的索引对应于其左兄弟节点的数量(因为在第二个示例中,根节点和6
子节点都被标记为0
)。更新:显然,第一次我只是误读了visit
示例——它使意图足够清楚……幸运的是,现在我正确地阅读了它,我觉得下面的答案是正确的
如果这是正确的,这是一个基于clojure.walk/postwark
的解决方案:
(defn index-vec-tree [vt]
[0 (walk/postwalk
(fn [node]
(if-not (vector? node)
node
(vec (map-indexed vector node))))
vt)])
通过给出的示例:
user> (index-vec-tree [6 7])
[0 [[0 6] [1 7]]]
user> (index-vec-tree 42)
[0 42]
更新:使用映射索引
的简单解决方案(在1.2中提供;在1.1中使用映射
+clojure.contrib.seq utils/index
):
user> (index-vec-tree [6 7])
[0 [[0 6] [1 7]]]
user> (index-vec-tree 42)
[0 42]
(defn index-vec-tree [vt]
(letfn [(iter [i vt] [i (if (vector? vt)
(vec (map-indexed iter vt))
vt)])]
(iter 0 vt)))