Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 94 additions & 22 deletions lib/tree.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,59 +2,131 @@ class TreeNode
attr_reader :key, :value
attr_accessor :left, :right

def initialize(key, val)
def initialize(key, val)
@key = key
@value = val
@left = nil
@right = nil
end
end
end

class Tree
attr_reader :root

def initialize
@root = nil
end

# Time Complexity:
# Space Complexity:
# Time Complexity: O(log n) is the best case which is a balanced tree, where n is the number of nodes. Worst case would be O(n) if each nod was more than the previous, or all less than the previous, which would just be a linked list.
# Space Complexity:O(1) only constant sized variables are used
def add(key, value)
raise NotImplementedError
node = TreeNode.new(key, value)
if @root.nil?
@root = node
return
end
current = @root
until current == nil
if current.key > node.key
if current.left == nil
current.left = node
return
else
current = current.left
end
else
if current.right == nil
current.right = node
return
else
current = current.right
end
end
end
end

# Time Complexity:
# Space Complexity:
# Time Complexity: O(log n) is the best case which is a balanced tree, where n is the number of nodes. Worst case would be O(n) if each nod was more than the previous, or all less than the previous, which would just be a linked list.
# Space Complexity:O(1) only constant sized variables are used
def find(key)
raise NotImplementedError
current = @root
until current == nil
if current.key > key
current = current.left
elsif current.key < key
current = current.right
else
return current.value
end
end
return nil
end

# Time Complexity:
# Space Complexity:
# Time Complexity: O(n) where n is the number of nodes. The inorder recurssive method is called once for each node, and the time complexity for each frame is constant.
# Space Complexity: Worst Case would be O(n^2) for a completely unbalanced tree, becuase you could have n stack frames and n arrays. Best case for a balances tree would be O(log n)^2 because you would have log n stack frames at once and log n arrays at once.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

O(n2)??? You are building an array of each key-value pair, and have the system stack being called on each node, but they're not nested. Remember arrays are passed by reference.

def inorder
raise NotImplementedError
node = @root
return inorder_recurssive(node, [])
end

# Time Complexity:
# Space Complexity:
def inorder_recurssive(curr_node, inorder_array)
return inorder_array if curr_node == nil

inorder_array = inorder_recurssive(curr_node.left, inorder_array)
inorder_array.append({ :key => curr_node.key, :value => curr_node.value })
inorder_array = inorder_recurssive(curr_node.right, inorder_array)
return inorder_array
end

# Time Complexity: O(n) where n is the number of nodes. The inorder recurssive method is called once for each node, and the time complexity for each frame is constant.
# Space Complexity: Worst Case would be O(n^2) for a completely unbalanced tree, becuase you could have n stack frames and n arrays. Best case for a balances tree would be O(log n)^2 because you would have log n stack frames at once and log n arrays at once.
def preorder
raise NotImplementedError
node = @root
return preorder_recurssive(node, [])
end

# Time Complexity:
# Space Complexity:
def preorder_recurssive(curr_node, preorder_array)
return preorder_array if curr_node == nil
preorder_array.append({ :key => curr_node.key, :value => curr_node.value })
preorder_array = preorder_recurssive(curr_node.left, preorder_array)
preorder_array = preorder_recurssive(curr_node.right, preorder_array)
end

# Time Complexity: O(n) where n is the number of nodes. The inorder recurssive method is called once for each node, and the time complexity for each frame is constant.
# Space Complexity: Worst Case would be O(n^2) for a completely unbalanced tree, becuase you could have n stack frames and n arrays. Best case for a balances tree would be O(log n)^2 because you would have log n stack frames at once and log n arrays at once.
def postorder
raise NotImplementedError
node = @root
return postorder_recurssive(node, [])
end

# Time Complexity:
# Space Complexity:
def postorder_recurssive(curr_node, postorder_array)
return postorder_array if curr_node == nil
postorder_array = postorder_recurssive(curr_node.left, postorder_array)
postorder_array = postorder_recurssive(curr_node.right, postorder_array)
postorder_array.append({ :key => curr_node.key, :value => curr_node.value })
end

# Time Complexity: O(n) where n is the number of nodes. The inorder recurssive method is called once for each node, and the time complexity for each frame is constant.
# Space Complexity: O(n) is the worst case because you would have n stack frames, where n is the number of nodes. Best case on a balamced tree would be O(log n) because you would have at most the height number of stack frames, which is log n.
def height
raise NotImplementedError
return 0 if @root == nil
node = @root
return height_recurssive(node, 1, 1)
end

def height_recurssive(curr_node, curr_height, max_height)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice tail recursive method.

return max_height if curr_node == nil

max_height = curr_height if curr_height > max_height
max_height = height_recurssive(curr_node.left, curr_height += 1, max_height)
curr_height -= 1
max_height = height_recurssive(curr_node.right, curr_height += 1, max_height)

return max_height
end

# Optional Method
# Time Complexity:
# Space Complexity:
# Time Complexity:
# Space Complexity:
def bfs
raise NotImplementedError
end
Expand Down
55 changes: 32 additions & 23 deletions test/tree_test.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
require_relative 'test_helper'

require_relative "test_helper"

Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new

describe Tree do
let (:tree) {Tree.new}
let (:tree) { Tree.new }

let (:tree_with_nodes) {
tree.add(5, "Peter")
Expand Down Expand Up @@ -37,23 +36,21 @@
end

it "will return the tree in order" do

expect(tree_with_nodes.inorder).must_equal [{:key=>1, :value=>"Mary"}, {:key=>3, :value=>"Paul"},
{:key=>5, :value=>"Peter"}, {:key=>10, :value=>"Karla"},
{:key=>15, :value=>"Ada"}, {:key=>25, :value=>"Kari"}]
expect(tree_with_nodes.inorder).must_equal [{ :key => 1, :value => "Mary" }, { :key => 3, :value => "Paul" },
{ :key => 5, :value => "Peter" }, { :key => 10, :value => "Karla" },
{ :key => 15, :value => "Ada" }, { :key => 25, :value => "Kari" }]
end
end


describe "preorder" do
it "will give an empty array for an empty tree" do
expect(tree.preorder).must_equal []
end

it "will return the tree in preorder" do
expect(tree_with_nodes.preorder).must_equal [{:key=>5, :value=>"Peter"}, {:key=>3, :value=>"Paul"},
{:key=>1, :value=>"Mary"}, {:key=>10, :value=>"Karla"},
{:key=>15, :value=>"Ada"}, {:key=>25, :value=>"Kari"}]
expect(tree_with_nodes.preorder).must_equal [{ :key => 5, :value => "Peter" }, { :key => 3, :value => "Paul" },
{ :key => 1, :value => "Mary" }, { :key => 10, :value => "Karla" },
{ :key => 15, :value => "Ada" }, { :key => 25, :value => "Kari" }]
end
end

Expand All @@ -63,21 +60,33 @@
end

it "will return the tree in postorder" do
expect(tree_with_nodes.postorder).must_equal [{:key=>1, :value=>"Mary"}, {:key=>3, :value=>"Paul"},
{:key=>25, :value=>"Kari"}, {:key=>15, :value=>"Ada"},
{:key=>10, :value=>"Karla"}, {:key=>5, :value=>"Peter"}]
expect(tree_with_nodes.postorder).must_equal [{ :key => 1, :value => "Mary" }, { :key => 3, :value => "Paul" },
{ :key => 25, :value => "Kari" }, { :key => 15, :value => "Ada" },
{ :key => 10, :value => "Karla" }, { :key => 5, :value => "Peter" }]
end
end

describe "breadth first search" do
it "will give an empty array for an empty tree" do
expect(tree.bfs).must_equal []
describe "height" do
it "will find the height of a tree" do
tree_with_nodes.add(9, "Jo")
tree_with_nodes.add(14, "Jane")
tree_with_nodes.add(4, "Jil")
expect(tree_with_nodes.height()).must_equal 4
end

it "will return an array of a level-by-level output of the tree" do
expect(tree_with_nodes.bfs).must_equal [{:key=>5, :value=>"Peter"}, {:key=>3, :value=>"Paul"},
{:key=>10, :value=>"Karla"}, {:key=>1, :value=>"Mary"},
{:key=>15, :value=>"Ada"}, {:key=>25, :value=>"Kari"}]
it "will return 0 for an empty tree" do
expect(tree.height()).must_equal 0
end
end
end

# describe "breadth first search" do
# it "will give an empty array for an empty tree" do
# expect(tree.bfs).must_equal []
# end

# it "will return an array of a level-by-level output of the tree" do
# expect(tree_with_nodes.bfs).must_equal [{ :key => 5, :value => "Peter" }, { :key => 3, :value => "Paul" },
# { :key => 10, :value => "Karla" }, { :key => 1, :value => "Mary" },
# { :key => 15, :value => "Ada" }, { :key => 25, :value => "Kari" }]
# end
# end
end