Итак, я получил очень общее представление о Clojure и хотел бы вычислить глубину дерева, определенного с использованием вектора, содержащего сами векторы. Например, [1 [2] [3 [4]]] будет представлять дерево, где 1 - корень, а [2] - дочерний элемент 1, а [3 [4]] - поддерево.

(defn height[tree]
(if(empty? tree)
    (1); Base case
    (inc (apply max (map  height (next tree))))); Calculate the height for every subtree and return maximum
)

Я думал, что этот метод сработает, поскольку он должен рекурсивно вычислять глубину каждого поддерева, чтобы вернуть максимальное значение. Однако при попытке запустить этот метод я получаю исключение «Недопустимый аргумент».

1
VTN 26 Апр 2016 в 13:53

2 ответа

Лучший ответ
  • (1) неверно. Он пытается выполнить 1 как функцию.
  • Вам нужно уметь справляться с листьями на дереве, которые не являются векторами.
  • Вызов next неверен - оставьте его в стороне.

Пытаться

(defn height [tree]
  (if (vector? tree)
   (if (empty? tree)
     1
     (inc (apply max (map height tree))))
    0))

Например,

(height [1 [2] [3 [4] ]]) ; 3

Чуть более простая версия

(defn height [tree]
  (if (vector? tree)
    (inc (apply max 0 (map height tree)))
    0))

Предоставляя начальный аргумент / аргумент по умолчанию 0 для max, мы имеем дело с пустой коллекцией без условия.

3
Thumbnail 26 Апр 2016 в 11:59

Хвостовой рекурсивный вариант с молниями:

(require '[clojure.zip :as z])

(defn height-2 [tree]
  (loop [curr (z/zipper coll? seq nil tree) h 0]
    (if (z/end? curr) h
        (recur (z/next curr)
               (if (z/branch? curr) h
                   (-> curr z/path count (max h)))))))

В ответе:

user> (height-2 [1 [2] [3 [4] ]])
3
user> (height-2 (nth (iterate (partial vector 1) []) 1000))
1000
user> (height-2 (nth (iterate (partial vector 1) []) 100000))
100000
6
leetwinski 26 Апр 2016 в 12:58