前提・実現したいこと
こんにちは。
プログラミング初心者なのですが、Rubyの練習問題を解いていてわからないところが出てきてしまったので質問させていただきました。
以下の問題は二分探索木の問題で、解答例を見ていて理解できていない部分を見つけました。
Rubyで独自にクラスを作成した場合、そのクラスのインスタンスメソッドとしてeachメソッドは定義されていないため、使いたい場合は自分で定義する必要があるということは分かるのですが、ここで定義されているBst#eachの仕組みがよく分からないです。
なぜ、Bst#each内では@leftに対してeachを呼び出すことで@leftに入ったBstクラスのインスタンス変数である@dataの2を取り出すことができるのでしょうか?
ためしにBst#each内で、self.each(&block)としてみたのですが、SystemStacErrorが発生してしまいました。SystemStacErrorはなぜ@left.eachの場合は発生しないのでしょうか?
発生している問題・エラーメッセージ
エラーなし
該当のソースコード
README
1# Binary Search Tree 2 3Insert and search for numbers in a binary tree. 4 5When we need to represent sorted data, an array does not make a good 6data structure. 7 8Say we have the array `[1, 3, 4, 5]`, and we add 2 to it so it becomes 9`[1, 3, 4, 5, 2]` now we must sort the entire array again! We can 10improve on this by realizing that we only need to make space for the new 11item `[1, nil, 3, 4, 5]`, and then adding the item in the space we 12added. But this still requires us to shift many elements down by one. 13 14Binary Search Trees, however, can operate on sorted data much more 15efficiently. 16 17A binary search tree consists of a series of connected nodes. Each node 18contains a piece of data (e.g. the number 3), a variable named `left`, 19and a variable named `right`. The `left` and `right` variables point at 20`nil`, or other nodes. Since these other nodes in turn have other nodes 21beneath them, we say that the left and right variables are pointing at 22subtrees. All data in the left subtree is less than or equal to the 23current node's data, and all data in the right subtree is greater than 24the current node's data. 25 26For example, if we had a node containing the data 4, and we added the 27data 2, our tree would look like this: 28 29 4 30 / 31 2 32 33If we then added 6, it would look like this: 34 35 4 36 / \ 37 2 6 38 39If we then added 3, it would look like this 40 41 4 42 / \ 43 2 6 44 \ 45 3 46 47And if we then added 1, 5, and 7, it would look like this 48 49 4 50 / \ 51 / \ 52 2 6 53 / \ / \ 54 1 3 5 7 55 56* * * * 57
Ruby
1class Bst 2 attr_reader :data, :left, :right 3 4 def initialize(data) 5 @data = data 6 end 7 8 def insert(data) 9 data > @data ? self.go_right(data) : self.go_left(data) 10 end 11 12 def go_right(data) 13 @right ? @right.insert(data) : @right = Bst.new(data) 14 end 15 16 def go_left(data) 17 @left ? @left.insert(data) : @left = Bst.new(data) 18 end 19 20 def each(&block) 21 return enum_for(:each) unless block_given? 22 @left.each(&block) if @left 23 block.call(data) 24 @right.each(&block) if @right 25 end 26end
Ruby
1require 'minitest/autorun' 2require_relative 'binary_search_tree' 3 4class BstTest < Minitest::Test 5 def test_data_is_retained 6 assert_equal 4, Bst.new(4).data 7 end 8 9 def test_inserting_less 10 #skip 11 four = Bst.new 4 12 four.insert 2 13 assert_equal 4, four.data 14 assert_equal 2, four.left.data 15 end 16 17 def test_inserting_same 18 #skip 19 four = Bst.new 4 20 four.insert 4 21 assert_equal 4, four.data 22 assert_equal 4, four.left.data 23 end 24 25 def test_inserting_right 26 #skip 27 four = Bst.new 4 28 four.insert 5 29 assert_equal 4, four.data 30 assert_equal 5, four.right.data 31 end 32 33 def test_complex_tree 34 #skip 35 four = Bst.new 4 36 four.insert 2 37 four.insert 6 38 four.insert 1 39 four.insert 3 40 four.insert 7 41 four.insert 5 42 assert_equal 4, four.data 43 assert_equal 2, four.left.data 44 assert_equal 1, four.left.left.data 45 assert_equal 3, four.left.right.data 46 assert_equal 6, four.right.data 47 assert_equal 5, four.right.left.data 48 assert_equal 7, four.right.right.data 49 end 50 51 def record_all_data(bst) 52 all_data = [] 53 bst.each { |data| all_data << data } 54 all_data 55 end 56 57 def test_iterating_one_element 58 #skip 59 assert_equal [4], record_all_data(Bst.new(4)) 60 end 61 62 def test_iterating_over_smaller_element 63 #skip 64 four = Bst.new 4 65 four.insert 2 66 assert_equal [2, 4], record_all_data(four) 67 end 68 69 def test_iterating_over_larger_element 70 #skip 71 four = Bst.new 4 72 four.insert 5 73 assert_equal [4, 5], record_all_data(four) 74 end 75 76 def test_iterating_over_complex_tree 77 #skip 78 four = Bst.new 4 79 four.insert 2 80 four.insert 1 81 four.insert 3 82 four.insert 6 83 four.insert 7 84 four.insert 5 85 assert_equal [1, 2, 3, 4, 5, 6, 7], record_all_data(four) 86 end 87 88 def test_each_returns_enumerator_if_no_block 89 #skip 90 91 tree = Bst.new 4 92 [2, 1, 3, 6, 7, 5].each { |x| tree.insert x } 93 each_enumerator = tree.each 94 95 assert_kind_of Enumerator, each_enumerator 96 97 (1..7).each { |x| assert_equal(x, each_enumerator.next) } 98 99 assert_raises(StopIteration) { each_enumerator.next } 100 end 101end 102
試したこと
ここに問題に対して試したことを記載してください。
補足情報(FW/ツールのバージョンなど)
ここにより詳細な情報を記載してください。
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/09/08 14:26
2018/09/08 15:45
2018/09/08 23:34