ruby - binary-search-tree
This commit is contained in:
		
							
								
								
									
										84
									
								
								ruby/binary-search-tree/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								ruby/binary-search-tree/README.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,84 @@ | ||||
| # Binary Search Tree | ||||
|  | ||||
| Insert and search for numbers in a binary tree. | ||||
|  | ||||
| When we need to represent sorted data, an array does not make a good | ||||
| data structure. | ||||
|  | ||||
| Say we have the array `[1, 3, 4, 5]`, and we add 2 to it so it becomes | ||||
| `[1, 3, 4, 5, 2]` now we must sort the entire array again! We can | ||||
| improve on this by realizing that we only need to make space for the new | ||||
| item `[1, nil, 3, 4, 5]`, and then adding the item in the space we | ||||
| added. But this still requires us to shift many elements down by one. | ||||
|  | ||||
| Binary Search Trees, however, can operate on sorted data much more | ||||
| efficiently. | ||||
|  | ||||
| A binary search tree consists of a series of connected nodes. Each node | ||||
| contains a piece of data (e.g. the number 3), a variable named `left`, | ||||
| and a variable named `right`. The `left` and `right` variables point at | ||||
| `nil`, or other nodes. Since these other nodes in turn have other nodes | ||||
| beneath them, we say that the left and right variables are pointing at | ||||
| subtrees. All data in the left subtree is less than or equal to the | ||||
| current node's data, and all data in the right subtree is greater than | ||||
| the current node's data. | ||||
|  | ||||
| For example, if we had a node containing the data 4, and we added the | ||||
| data 2, our tree would look like this: | ||||
|  | ||||
|       4 | ||||
|      / | ||||
|     2 | ||||
|  | ||||
| If we then added 6, it would look like this: | ||||
|  | ||||
|       4 | ||||
|      / \ | ||||
|     2   6 | ||||
|  | ||||
| If we then added 3, it would look like this | ||||
|  | ||||
|        4 | ||||
|      /   \ | ||||
|     2     6 | ||||
|      \ | ||||
|       3 | ||||
|  | ||||
| And if we then added 1, 5, and 7, it would look like this | ||||
|  | ||||
|           4 | ||||
|         /   \ | ||||
|        /     \ | ||||
|       2       6 | ||||
|      / \     / \ | ||||
|     1   3   5   7 | ||||
|  | ||||
| * * * * | ||||
|  | ||||
| For installation and learning resources, refer to the | ||||
| [exercism help page](http://exercism.io/languages/ruby). | ||||
|  | ||||
| For running the tests provided, you will need the Minitest gem. Open a | ||||
| terminal window and run the following command to install minitest: | ||||
|  | ||||
|     gem install minitest | ||||
|  | ||||
| If you would like color output, you can `require 'minitest/pride'` in | ||||
| the test file, or note the alternative instruction, below, for running | ||||
| the test file. | ||||
|  | ||||
| Run the tests from the exercise directory using the following command: | ||||
|  | ||||
|     ruby binary_search_tree_test.rb | ||||
|  | ||||
| To include color from the command line: | ||||
|  | ||||
|     ruby -r minitest/pride binary_search_tree_test.rb | ||||
|  | ||||
|  | ||||
| ## Source | ||||
|  | ||||
| Josh Cheek [https://twitter.com/josh_cheek](https://twitter.com/josh_cheek) | ||||
|  | ||||
| ## Submitting Incomplete Solutions | ||||
| It's possible to submit an incomplete solution so you can see how others have completed the exercise. | ||||
							
								
								
									
										30
									
								
								ruby/binary-search-tree/binary_search_tree.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								ruby/binary-search-tree/binary_search_tree.rb
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | ||||
| # class Bst | ||||
| class Bst | ||||
|   attr_reader :data, :left, :right | ||||
|  | ||||
|   def initialize(data) | ||||
|     @data = data | ||||
|   end | ||||
|  | ||||
|   def insert(data) | ||||
|     data <= @data ? insert_left(data) : insert_right(data) | ||||
|   end | ||||
|  | ||||
|   def each(&block) | ||||
|     return enum_for(:each) unless block_given? | ||||
|  | ||||
|     @left.each(&block) if left | ||||
|     yield data | ||||
|     @right.each(&block) if right | ||||
|   end | ||||
|  | ||||
|   private | ||||
|  | ||||
|   def insert_left(data) | ||||
|     @left ? @left.insert(data) : @left = self.class.new(data) | ||||
|   end | ||||
|  | ||||
|   def insert_right(data) | ||||
|     @right ? @right.insert(data) : @right = self.class.new(data) | ||||
|   end | ||||
| end | ||||
							
								
								
									
										101
									
								
								ruby/binary-search-tree/binary_search_tree_test.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								ruby/binary-search-tree/binary_search_tree_test.rb
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,101 @@ | ||||
| require 'minitest/autorun' | ||||
| require_relative 'binary_search_tree' | ||||
|  | ||||
| class BstTest < Minitest::Test | ||||
|   def test_data_is_retained | ||||
|     assert_equal 4, Bst.new(4).data | ||||
|   end | ||||
|  | ||||
|   def test_inserting_less | ||||
|     # skip | ||||
|     four = Bst.new 4 | ||||
|     four.insert 2 | ||||
|     assert_equal 4, four.data | ||||
|     assert_equal 2, four.left.data | ||||
|   end | ||||
|  | ||||
|   def test_inserting_same | ||||
|     # skip | ||||
|     four = Bst.new 4 | ||||
|     four.insert 4 | ||||
|     assert_equal 4, four.data | ||||
|     assert_equal 4, four.left.data | ||||
|   end | ||||
|  | ||||
|   def test_inserting_right | ||||
|     # skip | ||||
|     four = Bst.new 4 | ||||
|     four.insert 5 | ||||
|     assert_equal 4, four.data | ||||
|     assert_equal 5, four.right.data | ||||
|   end | ||||
|  | ||||
|   def test_complex_tree | ||||
|     # skip | ||||
|     four = Bst.new 4 | ||||
|     four.insert 2 | ||||
|     four.insert 6 | ||||
|     four.insert 1 | ||||
|     four.insert 3 | ||||
|     four.insert 7 | ||||
|     four.insert 5 | ||||
|     assert_equal 4, four.data | ||||
|     assert_equal 2, four.left.data | ||||
|     assert_equal 1, four.left.left.data | ||||
|     assert_equal 3, four.left.right.data | ||||
|     assert_equal 6, four.right.data | ||||
|     assert_equal 5, four.right.left.data | ||||
|     assert_equal 7, four.right.right.data | ||||
|   end | ||||
|  | ||||
|   def record_all_data(bst) | ||||
|     all_data = [] | ||||
|     bst.each { |data| all_data << data } | ||||
|     all_data | ||||
|   end | ||||
|  | ||||
|   def test_iterating_one_element | ||||
|     # skip | ||||
|     assert_equal [4], record_all_data(Bst.new(4)) | ||||
|   end | ||||
|  | ||||
|   def test_iterating_over_smaller_element | ||||
|     # skip | ||||
|     four = Bst.new 4 | ||||
|     four.insert 2 | ||||
|     assert_equal [2, 4], record_all_data(four) | ||||
|   end | ||||
|  | ||||
|   def test_iterating_over_larger_element | ||||
|     # skip | ||||
|     four = Bst.new 4 | ||||
|     four.insert 5 | ||||
|     assert_equal [4, 5], record_all_data(four) | ||||
|   end | ||||
|  | ||||
|   def test_iterating_over_complex_tree | ||||
|     # skip | ||||
|     four = Bst.new 4 | ||||
|     four.insert 2 | ||||
|     four.insert 1 | ||||
|     four.insert 3 | ||||
|     four.insert 6 | ||||
|     four.insert 7 | ||||
|     four.insert 5 | ||||
|     assert_equal [1, 2, 3, 4, 5, 6, 7], record_all_data(four) | ||||
|   end | ||||
|  | ||||
|   def test_each_returns_enumerator_if_no_block | ||||
|     # skip | ||||
|  | ||||
|     tree = Bst.new 4 | ||||
|     [2, 1, 3, 6, 7, 5].each { |x| tree.insert x } | ||||
|     each_enumerator = tree.each | ||||
|  | ||||
|     assert_kind_of Enumerator, each_enumerator | ||||
|  | ||||
|     (1..7).each { |x| assert_equal(x, each_enumerator.next) } | ||||
|  | ||||
|     assert_raises(StopIteration) { each_enumerator.next } | ||||
|   end | ||||
| end | ||||
		Reference in New Issue
	
	Block a user