#ruby #sum #binary-tree
#ruby #сумма #двоичное дерево
Вопрос:
У меня есть реализация двоичного дерева, как показано ниже. Я хотел бы добавить метод, который рекурсивно суммирует все значения узлов двоичного дерева:
class BST
class Node
attr_reader :value, :left, :right
def initialize(value)
@value = value
@left = nil
@right = nil
end
def insert(value)
if value <= @value
@left.nil? ? @left = Node.new(value) : @left.insert(value)
elsif value > @value
@right.nil? ? @right = Node.new(value) : @right.insert(value)
end
end
end
def initialize
@root = nil
end
def insert(value)
@root.nil? ? @root = Node.new(value) : @root.insert(value)
end
end
Я нашел ответ для других языков, но, к сожалению, не для Ruby.
Комментарии:
1. Что значит, вы нашли ответ для других языков, но не для Ruby? Логика точно такая же. С каким конкретно препятствием вы сталкиваетесь при его реализации?
2. @Amadan Я новичок и пытаюсь понять рекурсию. Хотя я понимаю принцип, я не могу перенести решение на других языках в Ruby…
3. Сумма узла — это значение узла плюс сумма всех дочерних элементов, отличных от нуля, верно? По крайней мере, попытайтесь перевести это в код, тогда мы сможем поговорить о том, что с этим не так, если вообще что-нибудь.
4. Хорошим началом было бы добавить пример дерева (и показать значение желаемой суммы). Поскольку ответов пока нет, вы могли бы рассмотреть возможность удаления вопроса, отредактировать для уточнения и добавить пример, затем восстановить. Таким образом, вы не будете испытывать нехватки времени для завершения редактирования и не привлечете больше отрицательных голосов или голосов за закрытие во время редактирования. ПОЭТОМУ существует правило, согласно которому для решения домашних задач (не предполагая, что это одна из них) от спрашивающего ожидается объяснение усилий, которые он / она предпринял для решения проблемы. Для этого не обязательно требуется код. Потенциально это хороший вопрос.
5. Re: «Сумма узла — это значение узла плюс сумма всех дочерних элементов, отличных от нуля, верно? По крайней мере, попытайтесь перевести это в код «. Вот что я попробовал внутри класса BST:
def sum(node=@root) return if node.nil? total = node.value sum(node.left) sum(node.right) end
однако он выдает «NoMethodError: неопределенный метод ` ‘ для nil: NilClass». Вот тут я и застрял.
Ответ №1:
Я думаю, что ваш код в комментариях был:
def sum(node=@root)
return if node.nil?
total = node.value
sum(node.left)
sum(node.right)
end
Идея почти в порядке. В nil
узлах нет суммирования; и вы суммируете значение текущего узла, левого узла и правого узла. Вот ошибки:
-
total = node.value
это мы видим впервыеtotal
. Это инициализирует егоnil
. Когда вы пытаетесь добавить к немуnode.value
, вы получаете описанную вами ошибку. Чтобы избежать этого, оноtotal
должно уже существовать, или вы можете просто присвоитьnode.value
ему значение. -
Если функция завершается без выполнения
return
инструкции, она возвращает последнее вычисленное выражение; в данном случаеsum(node.right)
. Не было бы лучше, если быsum
возвращалосьtotal
? -
И наоборот,
sum(node.left)
предположительно, выполнит некоторое суммирование… но его возвращаемое значение отбрасывается. Возможно, имеет смысл добавить это вtotal
. Говоря об итогах, возможно, нам следует сделать то же самое дляsum(node.right)
. -
Наконец,
return if node.nil?
говорится, что вы отказываетесь суммировать узлы, которые на самом деле не являются узлами. Это здорово … за исключением того, что этоreturn
возвращаетnil
, и если вы попытаетесь с чем-то суммировать anil
, это не сработает. Здесь есть два решения: отказаться от суммирования узла перед его вводом или сказать, что нулевой узел имеет значение 0, которое не влияет на сумму.
Собрав все это вместе, вот мои две версии:
# refuse to enter a nil node:
def sum(node=@root)
total = node.value
total = sum(node.left) unless node.left.nil?
total = sum(node.right) unless node.right.nil?
total
end
# treat nil nodes as if they were zeroes:
def sum(node=@root)
return 0 if node.nil?
node.value sum(node.left) sum(node.right)
end
Комментарии:
1. Большое вам спасибо за ваш подробный ответ! Это в точности объясняет все проблемы, с которыми я боролся все это время и которые заставляли меня чесать голову в течение нескольких дней, пока я, наконец, не прибегнул к SO. Также спасибо за руководство по использованию SO, также спасибо @ Cary ! P.S. Моя попытка повысить голос не регистрируется из-за моего слишком низкого рейтинга репутации… Еще раз спасибо — вы были очень полезны!