diff --git a/lib/tree.rb b/lib/tree.rb index c0d4b51..825a70d 100644 --- a/lib/tree.rb +++ b/lib/tree.rb @@ -16,51 +16,165 @@ def initialize @root = nil end - # Time Complexity: - # Space Complexity: + # Time Complexity: O(log n) - omit half of dataset to add a value if tree is balanced + # Space Complexity: O(1) to insert a node def add(key, value) - raise NotImplementedError + if key.nil? || value.nil? + return nil + end + + if @root.nil? + @root = TreeNode.new(key, value) + return + end + + insert_node = TreeNode.new(key, value) + current_root = @root + + while !current_root.nil? + trailing_node = current_root + + if key <= current_root.key + current_root = current_root.left + else + current_root = current_root.right + end + end + + if key <= trailing_node.key + trailing_node.left = insert_node + else + trailing_node.right = insert_node + end end - # Time Complexity: - # Space Complexity: + # Time Complexity: Ologn - omit half of dataset (if balanced) to find a value + # Space Complexity: O(1) Constant def find(key) - raise NotImplementedError + #begin with root node, returns value + return unless !@root.nil? + + current_node = @root + + while current_node != nil + if key == current_node.key + return current_node.value + elsif key <= current_node.key + current_node = current_node.left + else + current_node = current_node.right + end + end + + return nil end - # Time Complexity: - # Space Complexity: + # Time Complexity: O(n) because we visit each node once + # Space Complexity: O(h) where h is equal to height of tree unless tree is imbalanced, then O(n) def inorder - raise NotImplementedError + root_node = @root + array = [] + return bst_inorder(root_node, array) + end + + def bst_inorder(node, arr) + if node + bst_inorder(node.left, arr) if node.left + arr << {:key => node.key, :value => node.value} + bst_inorder(node.right, arr) if node.right + end + return arr end - # Time Complexity: - # Space Complexity: + + + # Time Complexity: O(n) because we visit each node once + # Space Complexity: O(h) where h is equal to height of tree unless tree is imbalanced, then O(n) def preorder - raise NotImplementedError + array = [] + root_node = @root + return bst_preorder(root_node, array) end - # Time Complexity: - # Space Complexity: + def bst_preorder(node, arr) + if !node + arr << {:key => node.key, :value => node.value} + bst_preorder(node.left, arr) if node.left + bst_preorder(node.right, arr) if node.right + end + + return arr + end + + # Time Complexity: O(n) because we visit each node once + # Space Complexity: O(h) where h is equal to height of tree unless tree is imbalanced, then O(n) def postorder - raise NotImplementedError + array = [] + root_node = @root + return bst_postorder(root_node, array) end - # Time Complexity: - # Space Complexity: + def bst_postorder(node, arr) + if node + bst_postorder(node.left, arr) if node.left + bst_postorder(node.right, arr) if node.right + arr << {:key => node.key, :value => node.value} + end + return arr + end + + # Time Complexity: O(n) because you have to check each node/subtree in the tree to determine height + # Space Complexity: O(logn) unless unbalanced, then O(n) def height - raise NotImplementedError + current = @root + return 0 if @root.nil? + + return tree_height(current) + + end + + def tree_height(node) + #find the height of the largest subtree + root node + height_left = 0 + height_right = 0 + + if node == nil + return 0 + else + height_left = tree_height(node.left) if node.left + height_right = tree_height(node.right) if node.right + height_left > height_right ? 1 + height_left : 1 + height_right + end end # Optional Method - # Time Complexity: - # Space Complexity: + # Time Complexity: O(n) because we visit every node + # Space Complexity: O(n) because I am storing all bfs nodes in an array def bfs - raise NotImplementedError + node = @root + array = [] + return breadth_first(node, array) + end + + def breadth_first(node, arr) + current = node + levels_list = [] + i = 0 + + return arr if node.nil? + # add level by level + while i <= levels_list.length + arr << {:key => current.key, :value => current.value} + levels_list << current.left if current.left + levels_list << current.right if current.right + current = levels_list[i] + i+= 1 + end + return arr end # Useful for printing def to_s - return "#{self.inorder}" + puts "#{self.inorder}" end end diff --git a/test/tree_test.rb b/test/tree_test.rb index 8811f14..ddf786c 100644 --- a/test/tree_test.rb +++ b/test/tree_test.rb @@ -1,5 +1,5 @@ require_relative 'test_helper' - +require "minitest/skip_dsl" Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new @@ -80,4 +80,21 @@ {:key=>15, :value=>"Ada"}, {:key=>25, :value=>"Kari"}] end end + + describe "bst height" do + it "will return 0 if the root node is nil" do + expect(tree.height).must_equal 0 + end + + it "will give the correct height of a binary search tree" do + expect(tree_with_nodes.height).must_equal 4 + end + + it "will give the correct height of a binary search tree" do + tree_with_nodes.add(30, "Tatiana") + expect(tree_with_nodes.height).must_equal 5 + end + + end + end \ No newline at end of file