clojure - 从输入创建二叉树

时间:2015-08-20 16:32:18

标签: clojure

我正在尝试解决this问题,您需要创建一个如下所示的二叉树:

              1
             / \
            2   3
           /    /
          4    5
         /    /
        /    /\
       /    /  \
       6   7    8
        \      / \
         \    /   \
          9  10   11

从此输入中,-1表示空节点

[2 4][4 -1][5 -1][6 -1][7 8][-1 -9][-1 -1][10 11][-1 -1]

我正在努力从这个输入中创建树

到目前为止,我的代码看起来像这样:

    (ns scratch.core
      (require [clojure.string :as str :only (split-lines join split)]))

    (defn numberify [str]
      (vec (map read-string (str/split str #" "))))

    (defrecord TreeNode [val left right])

    (defn tree-map [idx itm]
      (let [side (if (= 0 idx) :left :right)]
        {:val itm :side side :index idx}))

    (defn build-tree
      [node xs]
      (let [process-branch (fn process-branch [[counter t'] l]
                             (if-not (= (:val l) -1)
                               (let [next-branch (nth xs counter)]
                                 (prn "=============")
                                 (prn l)
                                 (prn counter)
                                 (prn next-branch)
                                 (prn "=============")
                                 [(inc counter) t'])
                               [counter t']))
            mark-branch (fn mark-branch [x]
                          (map-indexed tree-map x))
            [counter tree] (reduce (fn [[counter tree] x]
                                     (reduce process-branch
                                             [counter tree]
                                             (mark-branch x)))
                                   [1 node] xs)]
        tree))

(let [input "11\n2 3\n4 -1\n5 -1\n6 -1\n7 8\n-1 9\n-1 -1\n10 11\n-1 -1\n-1 -1\n-1 -1"
      lines (str/split-lines input)
      tl (read-string (first lines))
      tree-lines (map numberify (drop 1 (take (inc tl) lines)))
      tree (build-tree (TreeNode. 1 nil nil) tree-lines)])

目前上述代码将打印出来:

"============="
{:val 2, :side :left, :index 0}
1
[4 -1]
"============="
"============="
{:val 3, :side :right, :index 1}
2
[5 -1]
"============="
"============="
{:val 4, :side :left, :index 0}
3
[6 -1]
"============="
;; etc.

所以我有正确的位来组成树,例如节点2从[4 -1]创建分支,但我正在努力的是如何将它们添加到树而不使树变得可变。

1 个答案:

答案 0 :(得分:1)

这是我创建树的方法。它使用没有loop的递归,所以如果给它一堆行,它会炸掉堆栈。如果需要,我可以用loop实现它。

sample.txt是一个文件,其中包含位于资源目​​录中的完整输入(即第一行是节点数)。

(defn read-input [f]
  (let [[n-str & node-str] (-> (slurp f)
                               clojure.string/split-lines)
        n (Integer/parseInt n-str)]
    (->> (map vector (range 1 n) node-str)
         (map (fn [[k v]]
                (->> (clojure.string/split v #" ")
                     (mapv #(Integer/parseInt %))
                     (vector k))))
         (into {}))))

(defrecord TreeNode [val left right])

(defn make-tree [i m]
  (when-let [[l r] (get m i)]
    (->TreeNode i (make-tree l m) (make-tree r m))))

(->> (clojure-scratch.core/read-input (clojure.java.io/resource "sample.txt"))
     (clojure-scratch.core/make-tree 1))

=> #clojure_scratch.core.TreeNode{:val 1, :left #clojure_scratch.core.TreeNode{:val 2, :left #clojure_scratch.core.TreeNode{:val 4, :left #clojure_scratch.core.TreeNode{:val 6, :left nil, :right #clojure_scratch.core.TreeNode{:val 9, :left nil, :right nil}}, :right nil}, :right nil}, :right #clojure_scratch.core.TreeNode{:val 3, :left #clojure_scratch.core.TreeNode{:val 5, :left #clojure_scratch.core.TreeNode{:val 7, :left nil, :right nil}, :right #clojure_scratch.core.TreeNode{:val 8, :left #clojure_scratch.core.TreeNode{:val 10, :left nil, :right nil}, :right nil}}, :right nil}}