From a317a96ee8bdd52defe3d73b8f746ddab753a0f3 Mon Sep 17 00:00:00 2001 From: Mariya Burrows Date: Mon, 17 Feb 2020 21:52:09 -0800 Subject: [PATCH] finished the linked list hw --- lib/linked_list.rb | 173 +++++++++++++++++++++++++++++++++++---- test/linked_list_test.rb | 84 +++++++++---------- 2 files changed, 200 insertions(+), 57 deletions(-) diff --git a/lib/linked_list.rb b/lib/linked_list.rb index 8dee5e8d..6cb0f5ad 100644 --- a/lib/linked_list.rb +++ b/lib/linked_list.rb @@ -19,67 +19,190 @@ def initialize # method to add a new node with the specific data value in the linked list # insert the new node at the beginning of the linked list def add_first(value) - raise NotImplementedError + @head = Node.new(value, @head) end # method to find if the linked list contains a node with specified value # returns true if found, false otherwise def search(value) - raise NotImplementedError + current = @head + until current.nil? + return true if current.data == value + current = current.next + end + + return false end # method to return the max value in the linked list # returns the data value and not the node def find_max - raise NotImplementedError + current = @head + return nil if current.nil? + max = current.data + + until current.nil? + if current.data > max + max = current.data + end + current = current.next + end + + return max end # method to return the min value in the linked list # returns the data value and not the node def find_min - raise NotImplementedError + current = @head + return nil if current.nil? + min = current.data + + until current.nil? + if current.data < min + min = current.data + end + current = current.next + end + + return min end # method that returns the length of the singly linked list def length - raise NotImplementedError + current = @head + return 0 if current.nil? + length = 0 + + until current.nil? + length += 1 + current = current.next + end + return length end # method that returns the value at a given index in the linked list # index count starts at 0 # returns nil if there are fewer nodes in the linked list than the index value def get_at_index(index) - raise NotImplementedError + current = @head + length = 0 + + until current.nil? + length += 1 + current = current.next + end + + return nil if length < index + + current = @head + index_value = current.data + + (index + 1).times do + index_value = current.data + current = current.next + end + + return index_value end # method to print all the values in the linked list def visit - raise NotImplementedError + current = @head + return nil if head.nil? + + until current.nil? + p current.data + end + end # method to delete the first node found with specified value def delete(value) - raise NotImplementedError + return nil if @head.nil? + current = @head + + if current.data == value + return @head = current.next + end + + previous = nil + continuing_node = nil + + until current.next.nil? || current.next.data == value + current = current.next + end + + return nil if current.next.nil? + previous = current + continuing_node = previous.next.next + previous.next = continuing_node + end # method to reverse the singly linked list # note: the nodes should be moved and not just the values in the nodes def reverse - raise NotImplementedError + previous = nil + current = @head + return nil if current.nil? + next_node = current.next + current.next = nil + + + until next_node.nil? + previous = current + current = next_node + next_node = current.next + current.next = previous + end + + @head = current + end ## Advanced Exercises # returns the value at the middle element in the singly linked list def find_middle_value - raise NotImplementedError + current = @head + temp = current + length = 0 + + until current.nil? + length += 1 + temp = temp.next + end + + middle_node = nil + (length / 2).times do + middle_node = current.data + current = current.next + end + + return middle_node end # find the nth node from the end and return its value # assume indexing starts at 0 while counting to n def find_nth_from_end(n) - raise NotImplementedError + nth_node = nil + current = @head + temp = @head + length = 0 + + until temp.nil? + length += 1 + temp = temp.next + end + + (length - n).times do + nth_node = current.data + current = current.next + end + + return nth_node end # checks if the linked list has a cycle. A cycle exists if any node in the @@ -94,24 +217,44 @@ def has_cycle # returns the value in the first node # returns nil if the list is empty def get_first - raise NotImplementedError + current = @head + return nil if current.nil? + return current.data end # method that inserts a given value as a new last node in the linked list def add_last(value) - raise NotImplementedError + if !@head + @head = Node.new(value) + return @head + else + current = @head + end + + until current.next.nil? + current = current.next + end + + current.next = Node.new(value) + end # method that returns the value of the last node in the linked list # returns nil if the linked list is empty def get_last - raise NotImplementedError + current = @head + return nil if current.nil? + + until current.next.nil? + current = current.next + end + + return current.data end # method to insert a new node with specific data value, assuming the linked # list is sorted in ascending order def insert_ascending(value) - raise NotImplementedError end # Helper method for tests diff --git a/test/linked_list_test.rb b/test/linked_list_test.rb index d169c9a0..f8c5c49b 100644 --- a/test/linked_list_test.rb +++ b/test/linked_list_test.rb @@ -12,73 +12,73 @@ before do @list = LinkedList.new end - + describe 'initialize' do it 'can be created' do - + # Assert expect(@list).must_be_kind_of LinkedList end end - + describe 'add_first & get_first' do it 'can add values to an empty list' do # Act @list.add_first(3) - + # Assert expect(@list.get_first).must_equal 3 end - + it 'will put the last added item to the front of the list' do # Act @list.add_first(1) @list.add_first(2) - + # Assert expect(@list.get_first).must_equal 2 - + # Act again @list.add_first(3) - + # Assert expect(@list.get_first).must_equal 3 end - + it 'will return `nil` for `getFirst` if the list is empty' do - + expect(@list.get_first).must_be_nil end end - + describe "search" do it "can find an element" do @list = LinkedList.new @list.add_first(3) @list.add_first(2) - + expect(@list.search(3)).must_equal true - + expect(@list.search(2)).must_equal true end - + it "returns false if the element is not in the list" do - @list = LinkedList.new - @list.add_first(3) - @list.add_first(2) - expect(@list.search("pasta")).must_equal false + @list = LinkedList.new + @list.add_first(3) + @list.add_first(2) + expect(@list.search("pasta")).must_equal false end - + it "returns false for an empty list" do - expect(@list.search(3)).must_equal false + expect(@list.search(3)).must_equal false end end - + describe "length" do it "will return 0 for an empty list" do expect(@list.length).must_equal 0 end - + it "will return the length for nonempty lists" do count = 0 while count < 5 @@ -88,54 +88,54 @@ end end end - + describe "addLast & getLast" do it "will add to the front if the list is empty" do @list.add_last(1) expect(@list.get_first).must_equal 1 end - + it "will put new items to the rear of the list" do @list.add_last(2) expect(@list.length).must_equal 1 expect(@list.get_last).must_equal 2 - + @list.add_last(3) expect(@list.get_first).must_equal 2 expect(@list.get_last).must_equal 3 expect(@list.length).must_equal 2 - + @list.add_last(4) expect(@list.get_first).must_equal 2 expect(@list.get_last).must_equal 4 expect(@list.length).must_equal 3 end end - + describe 'get_at_index' do it 'returns nil if the index is outside the bounds of the list' do expect(@list.get_at_index(3)).must_be_nil end - + it 'can retrieve an item at an index in the list' do @list.add_first(1) @list.add_first(2) @list.add_first(3) @list.add_first(4) - + expect(@list.get_at_index(0)).must_equal 4 expect(@list.get_at_index(1)).must_equal 3 expect(@list.get_at_index(2)).must_equal 2 expect(@list.get_at_index(3)).must_equal 1 end end - + describe 'max and min values' do it 'returns nil if the list is empty' do expect(@list.find_max()).must_be_nil expect(@list.find_min()).must_be_nil end - + it 'can retrieve the max and min values in the list' do count = 0 while count < 5 @@ -144,28 +144,28 @@ expect(@list.find_min).must_equal 0 count += 1 end - + @list.add_last(100) @list.add_first(-12) expect(@list.find_max).must_equal 100 expect(@list.find_min).must_equal(-12) end end - + describe "delete" do it "delete from empty linked list is a no-op" do expect(@list.length).must_equal 0 @list.delete(4) expect(@list.length).must_equal 0 end - + it "can delete valid values from list" do @list.add_last(9) @list.add_last(10) @list.add_first(4) @list.add_first(3) @list.add_first(2) - + # delete fist node (requires updating head) @list.delete(2) expect(@list.get_first).must_equal 3 @@ -173,7 +173,7 @@ expect(@list.get_last).must_equal 10 expect(@list.find_max).must_equal 10 expect(@list.find_min).must_equal 3 - + # delete last node @list.delete(10) expect(@list.get_first).must_equal 3 @@ -181,7 +181,7 @@ expect(@list.get_last).must_equal 9 expect(@list.find_max).must_equal 9 expect(@list.find_min).must_equal 3 - + # delete fist node (requires updating head) @list.delete(4) expect(@list.get_first).must_equal 3 @@ -191,18 +191,18 @@ expect(@list.find_min).must_equal 3 end end - + describe "nth_from_the_end" do it 'returns nil if n is outside the bounds of the list' do expect(@list.find_nth_from_end(3)).must_be_nil end - + it 'can retrieve an item at index n from the end in the list' do @list.add_first(1) @list.add_first(2) @list.add_first(3) @list.add_first(4) - + expect(@list.find_nth_from_end(0)).must_equal 1 expect(@list.find_nth_from_end(1)).must_equal 2 expect(@list.find_nth_from_end(2)).must_equal 3 @@ -210,7 +210,7 @@ expect(@list.find_nth_from_end(4)).must_be_nil end end - + describe "reverse" do it 'can retrieve an item at index n from the end in the list' do @list.add_first(4) @@ -218,7 +218,7 @@ @list.add_first(2) @list.add_first(1) @list.reverse - + expect(@list.find_nth_from_end(0)).must_equal 1 expect(@list.find_nth_from_end(1)).must_equal 2 expect(@list.find_nth_from_end(2)).must_equal 3