所以我要通过OdinProject并开始使用" BinaryTree"一部分。我编写了一个二叉树,但只能用C ++编写指针。因此,如果没有指针,我对节点的连接方式会更加困惑:
class Node
attr_accessor :value, :parent, :left, :right
@@nodes = 0
def self.nodes
@@nodes
end
def initialize(value, parent=nil)
@value = value
@parent = parent
@left = nil
@right = nil
@@nodes += 1
end
end
class BinaryTree
def initialize
@root = nil
end
def build_tree(arr)
arr.each {|el| add_child(el,@root)}
@root
end
def add_child(value,node)
if @root.nil?
@root = Node.new(value)
else
if value < node.value
node.left.nil? ? node.left = Node.new(value,node) : add_child(value,node.left)
elsif value > node.value
node.right.nil? ? node.right = Node.new(value,node) : add_child(value,node.right)
end
end
return node
end
end
我已经完成了一些基本的打印功能,并且SEEMS正常工作,但我想知道这对于更了解ruby的其他人是否正确。 (旁注:我意识到这不能处理重复的数字)。我错过了&#34;建筑&#34;树的一部分。
我担心的原因是看到很多不同的&#34; build&#34;实现。例如,从中点开始,或仅仅是为了#34;排序&#34;阵列
答案 0 :(得分:2)
欢迎来到红宝石世界!要小心你可能真的喜欢它,永远不会回到另一种语言:)
以下是我可以给你的一些评论:
当你想知道你的代码是否正确时,首先要用不同的输入来测试它。您可以在控制台中手动完成,也可以编写将在开发过程中跟随您的测试。
快速测试您的工作方法是在to_s
课程中定义Node
方法。例如,这将允许检查您的树是否已订购:
class Node
…
def to_s
"#{left} #{value} #{right}".strip
end
end
to_s
是将对象转换为字符串时使用的默认ruby方法。例如,你可以这样做:
#> puts BinaryTree.new.build_tree([5, 9, 1, 6])
1 5 6 9
为了您的安心,您可以描述一些测试,这些测试将允许您编写代码并对其进行修改,并检查它是否仍然有效。我建议minitest很容易做到。
require 'minitest/autorun'
describe BinaryTree do
before do
@constructor = BinaryTree.new
end
describe 'when given an array' do
it 'sorts it' do
@constructor.build_tree([1, 3, 2]).to_s.must_equal '1 2 3'
end
end
describe 'when given an array with duplicates' do
it 'builds the correct tree' do
@constructor.build_tree([1, 3, 2, 3]).to_s.must_equal '1 2 3 3'
end
end
end
如果ruby -Ilib:test binary_tree.rb
是放置代码的文件,则可以使用binary_tree.rb
运行它。
正如您所提到的,您将看到重复的代码不起作用。
您可以通过删除if…elsif
块中的条件来使其工作。
然后,您可以根据需要随时处理代码并运行测试,以确保您没有破坏任何内容。
每次有边缘情况时,您都不确定代码是否处理,只需将其置于测试中即可。
如果计算二叉树中的节点数,那么Node.nodes
方法可能不是您想要的。
它应该在Node
的实例中,而不是在类本身中:如果您有多个树,则每个树都会考虑所有节点。
你写的一些内容在ruby中可能有不同的表达方式:
attr_accessor parent
是
def parent
@parent
end
def parent=(other)
@parent = other
end
在ruby中,如果未声明实例变量@parent
,则默认值为nil
,调用node.parent
也会返回nil
。
初始化程序中不需要这两行:
@left = nil
@right = nil
如果方法中的最后一条指令是退货,则不需要return
关键字。这就是我用上面的to_s
方法做的。
我认为当命名参数不明显时更清晰。
例如,调用Node.new(value, node)
并不能真正帮助理解这两个参数是什么。我得到一个节点应该有一个值,但第二个参数是什么?
您可以定义:
def initialize(value, parent: nil)
# Same as before
end
并使用Node.new(value, parent: node)
或Node.new(value)
您的BinaryTree#add_child
方法应该在节点上。您正在向节点添加子项。移动它,所以你不需要你的第二个参数:
add_child(value, node.right)
变为node.right.add_child(value)
class Node
...
def add_child(other_value)
if other_value < value
left.nil? ? self.left = Node.new(other_value, parent: self) : left.add_child(other_value)
else
right.nil? ? self.right = Node.new(other_value, parent: self) : right.add_child(other_value)
end
end
end
class BinaryTree
...
def add_child(value)
if @root.nil?
@root = Node.new(value)
else
@root.add_child(value)
end
@root
end
end
当你在那里时,你也可以摆脱build_tree
课程中的BinaryTree
,并将其移至Node
。
我希望它能帮助你完成Ruby之旅。