Last active
December 26, 2015 22:49
-
-
Save socksy/7225668 to your computer and use it in GitHub Desktop.
Post-order traversal with a zipper in clojure
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;WARNING: this puts your entire tree in memory, so if you're using zippers | |
;to avoid that, do not use this. | |
;Also, potentially terrible clojure. I only learned this a few days ago | |
;couldn't find any way to do this online except for a single | |
;stackoverflow that didn't actually use zippers | |
(require '[clojure.zip :as zip]) | |
(defn zip-down [loc] | |
"Zips to the bottom of the tree from this loc" | |
(loop [p loc] | |
(if (zip/branch? p) | |
(do (def cnext-stack (cons p cnext-stack)) | |
(recur (zip/down p))) | |
p))) | |
;visited nodes | |
;remember to reset after a traversal | |
(def cnext-stack (list)) | |
(defn cnext | |
"Basically the same as clojure.zip/next, except postorder traversal." | |
([loc] (cnext loc cnext-stack)) | |
([loc stack] | |
(if (= :end (loc 1)) | |
loc | |
(or | |
;branch node and visited before? | |
(when (and (zip/branch? loc) (nil? (some #(= loc %) stack))) | |
(do (def cnext-stack (cons loc stack)) | |
(zip-down loc))) | |
;if sibling, go to it and zip down | |
(when (zip/right loc) (-> loc zip/right zip-down)) | |
(if (zip/up loc) | |
(zip/up loc) | |
[(zip/node loc) :end]))))) | |
(defn search | |
"Takes a zipper, and optionally a visit/edit function" | |
([zipper] (search zipper nil)) | |
([zipper edit] | |
(do (def cnext-stack (list)) | |
(loop [loc zipper] | |
(if (zip/end? loc) | |
(zip/root loc) | |
(do | |
(when edit (when-let [edited (edit loc)] | |
(zip/replace loc edited))) | |
(recur (cnext loc cnext-stack)))))))) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment