Ruby,这棵二叉树对吗?
因此,我正在进行OdinProject,并从“二进制树”部分开始。我已经编写了一个二叉树,但只用C++使用指针。因此,如果没有指针,我会对节点的连接方式更加困惑:Ruby,这棵二叉树对吗?,ruby,binary-search-tree,Ruby,Binary Search Tree,因此,我正在进行OdinProject,并从“二进制树”部分开始。我已经编写了一个二叉树,但只用C++使用指针。因此,如果没有指针,我会对节点的连接方式更加困惑: class Node attr_accessor :value, :parent, :left, :right @@nodes = 0 def self.nodes @@nodes end def initialize(value, parent=nil) @value = value
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
类节点
属性访问器:值,:父对象,:左,:右
@@节点=0
def self.nodes
@@节点
结束
def初始化(值,父项=nil)
@价值=价值
@父=父
@左=零
@右=零
@@节点+=1
结束
结束
类二叉树
def初始化
@根=零
结束
def生成树(arr)
arr.each{| el | add|u child(el,@root)}
@根
结束
def add_子项(值,节点)
如果@root.nil?
@root=Node.new(值)
其他的
如果值node.value
node.right.nil?node.right=node.new(值,节点):添加子项(值,node.right)
结束
结束
返回节点
结束
结束
我已经完成了一些基本的打印功能,它似乎工作正常,但我想知道对于其他更了解ruby的人来说这是否正确。(旁注:我意识到这不会处理重复的数字)。我在树的“建筑”部分遗漏了什么
我担心的原因是看到很多不同的“构建”实现。例如,一个从中点开始的数组,或者这只是用于“排序”数组?欢迎来到ruby世界!当心,你可能真的很喜欢它,永远不会回到另一种语言:) 以下是我可以给你的一些评论: 测试 当您怀疑代码是否正确时,首先要做的是使用不同的输入测试代码。您可以在控制台中手动完成,也可以编写在开发过程中跟随您的测试 印刷 测试所做工作的一种快速方法是在
节点
类上定义to_s
方法。例如,这将允许检查您的树是否已排序:
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
通过测试
为了让您安心,您可以描述一些测试,这些测试将允许您编写代码、修改代码并检查代码是否仍在工作。我建议使用小型测试,这样做很容易
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:testbinary_tree运行它。如果binary_tree,则rb
是放置代码的文件
您将看到,正如您所提到的,重复的代码不起作用。
您可以通过删除if…elsif
块中的条件使其工作
然后,您可以编写代码并随时运行测试,这样您就可以确信自己没有破坏任何东西
每次您有一个边缘情况,您不确定您的代码处理,只是把它放在一个测试
计算节点数
如果要计算二叉树中的节点数,则Node.nodes
方法可能不是您想要的。
它应该在节点的实例中,而不是在类本身中:如果有多棵树,则每个树都会考虑所有节点
红宝石
您编写的一些内容可以用ruby进行不同的表达:
零是不必要的
attr\u accessor parent
是
def parent
@parent
end
def parent=(other)
@parent = other
end
在ruby中,如果未声明实例变量@parent
,则默认情况下它的值为nil
,并且调用节点。parent
也将返回nil
初始值设定项中不需要这两行:
@left = nil
@right = nil
不必退货
如果方法中的最后一条指令是return,则不需要return
关键字。这就是我用上面的to\s
方法所做的
命名参数
我认为在参数不明显的情况下使用命名参数更干净。
例如,调用Node.new(value,Node)
实际上无助于理解这两个参数的用途。我知道一个节点应该有一个值,但第二个参数是什么
您可以定义:
def initialize(value, parent: nil)
# Same as before
end
用Node.new(值,父节点)
或Node.new(值)
糟糕的事情
将方法移动到它们所属的位置
您的BinaryTree#add_child
方法应位于节点上。您正在向节点添加一个子节点。将其移到那里,这样就不需要第二个参数:
add\u child(值,node.right)
变成node.right.add\u child(值)
类节点
...
def add_子项(其他_值)
如果其他_值<值
左。零?self.left=Node.new(其他_值,父项:self):left.add_子项(其他_值)
其他的
对。零?self.right=Node.new(其他值,父项:self):右。添加子项(其他值)
结束
结束
结束
类二叉树
...
def add_子项(值)
如果@root.nil?
@root=Node.new(值)
其他的
@根目录。添加子目录(值)
结束
@根
结束
结束
在那里,您还可以在BinaryTree
类中摆脱build_tree
,并将其移动到节点
我希望它能帮助您完成Ruby之旅。欢迎来到Ruby世界!当心,你可能真的很喜欢它,永远不会回到另一种语言:)
以下是我可以给你的一些评论:
测试
当您怀疑代码是否正确时,首先要做的是使用不同的输入测试代码。您可以在控制台中手动完成,也可以编写在开发过程中跟随您的测试
印刷
测试所做工作的一种快速方法是在节点
类上定义to_s
方法。例如,这将允许检查您的树是否已排序:
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
通过测试
为了让您安心,您可以描述一些允许您编写代码的测试,例如