From 567249042e2bc97167edd894c862816914ea4144 Mon Sep 17 00:00:00 2001 From: Cynthia Cobb Date: Thu, 17 Aug 2017 16:13:27 -0700 Subject: [PATCH 1/2] making progress on many methods --- linked_list.rb | 283 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 201 insertions(+), 82 deletions(-) diff --git a/linked_list.rb b/linked_list.rb index bcf81853..9994998c 100644 --- a/linked_list.rb +++ b/linked_list.rb @@ -4,9 +4,9 @@ class Node attr_reader :data # allow external entities to read value but not write attr_accessor :next # allow external entities to read or write next node - def initialize(value) + def initialize(value, next_node=nil) @data = value - @next = next + @next = next_node end end @@ -19,36 +19,73 @@ 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 insert(value) - puts "Not implemented" + # puts "Not implemented" + # id node that new node should point to + if @head != nil + current = @head + @head = Node.new(value) + @head.next = current + else + @head = Node.new(value) + @head.next = nil + end end # method to find if the linked list contains a node with specified value # returns true if found, false otherwise def search(value) - puts "Not implemented" + # puts "Not implemented" + current = @head + until current.next == nil + return true if current.value == value + 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 - puts "Not implemented" + current = @head + max = current.data + while current + max = current.data if current.data > max + 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 - puts "Not implemented" + current = @head + min = current.data + while current.next != nil + min = current.data if current.data < min + current = current.next + end + return min end # method that returns the length of the singly linked list def length - puts "Not implemented" + length = 0 + current = @head + while current + length += 1 + current = current.next + end + return length end # method to return the value of the nth element from the beginning # assume indexing starts at 0 while counting to n def find_nth_from_beginning(n) - puts "Not implemented" + current = @head + n.times do + current = current.next + end + # p current + return current.data end # method to insert a new node with specific data value, assuming the linked @@ -59,37 +96,119 @@ def insert_ascending(value) # method to print all the values in the linked list def visit - puts "Not implemented" + current = @head + while current + p current.data + current = current.next + end end # method to delete the first node found with specified value def delete(value) - puts "Not implemented" + # puts "Not implemented" + current = @head + previous = nil + while current.next + if current.data == value + # # need to know the next node + # # set the previous node to this next node --> knowing index/position would be nice + # next_node = current.next + current = current.next + previous.next = current + break + end + current = current.next + previous = current + end + # p current + # p next_node + # # p position + # current = @head + # position.times do + # p current + # current = current.next + # end + # # p current + # # current.next = next_node end # method to reverse the singly linked list # note: the nodes should be moved and not just the values in the nodes + # time complex - constant - cause visiting each node once so depends on linklist size def reverse - puts "Not implemented" + # puts "Not implemented" + current = @head + previous = nil + temp = current.next + + while current + temp = current.next + current.next = previous + previous = current + current = temp + end + + @head = previous end ## Advanced Exercises # returns the value at the middle element in the singly linked list def find_middle_value - puts "Not implemented" + # puts "Not implemented" + # check input - head is nil return + # if head nex is nil return value at head + + # set slow head + # set fast head next + + # algo steps + # while fast is not nil + # update slow next + # update falst next + ## if fast next is not nil - update fast next + + # return value at slow + + return if @head == nil + return @head.data if @head.next == nil + + slow = @head + fast = @head.next + + while fast.next + slow = slow.next + fast = fast.next + fast = fast.next if fast.next + end + + return slow.data 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) puts "Not implemented" + # want to know length + # approach one - find length - then length - n - 1 is index + # iterate through the list again to the desired index/position + + # approach two - tranverse just once + # current and trailing tracking - trailing starts once current reaches the value you want, + # then when current reaches the end, the trailing count is the index from the end + end # checks if the linked list has a cycle. A cycle exists if any node in the # linked list links to a node already visited. # returns true if a cycle is found, false otherwise. def has_cycle - puts "Not implemented" + # puts "Not implemented" + # have a fast and node - when they reach the same position you have a cycle + + # two pointers/references, fast and slow, slown and fast start at head + # fast moves twice as fast + # if fast becomes nil - no cycle + # if fast and slow same node - then true cycle end # Creates a cycle in the linked list for testing purposes @@ -132,68 +251,68 @@ def create_cycle puts "BUG: Value at index 0 should be 1 and is #{value}" if value != 1 # print all elements -puts "Printing elements in the linked list:" -my_linked_list.visit +# puts "Printing elements in the linked list:" +# my_linked_list.visit # Insert ascending -puts "Adding 4 in ascending order." -my_linked_list.insert_ascending(4) -# check newly inserted value -puts "Checking values by calling find_nth_from_beginning method." -value = my_linked_list.find_nth_from_beginning(2) -puts "BUG: Value at index 2 should be 4 and is #{value}" if value != 4 -value = my_linked_list.find_nth_from_beginning(3) -puts "BUG: Value at index 3 should be 5 and is #{value}" if value != 5 -value = my_linked_list.find_nth_from_beginning(1) -puts "BUG: Value at index 1 should be 3 and is #{value}" if value != 3 +# puts "Adding 4 in ascending order." +# my_linked_list.insert_ascending(4) +# # check newly inserted value +# puts "Checking values by calling find_nth_from_beginning method." +# value = my_linked_list.find_nth_from_beginning(2) +# puts "BUG: Value at index 2 should be 4 and is #{value}" if value != 4 +# value = my_linked_list.find_nth_from_beginning(3) +# puts "BUG: Value at index 3 should be 5 and is #{value}" if value != 5 +# value = my_linked_list.find_nth_from_beginning(1) +# puts "BUG: Value at index 1 should be 3 and is #{value}" if value != 3 # Insert ascending -puts "Adding 6 in ascening order." -my_linked_list.insert_ascending(6) +# puts "Adding 6 in ascening order." +# my_linked_list.insert_ascending(6) # print all elements -puts "Printing elements in the linked list:" -my_linked_list.visit +# puts "Printing elements in the linked list:" +# my_linked_list.visit # vaidate length -puts "Confirming length of the linked list." -my_linked_list_length = my_linked_list.length -puts "BUG: Length should be 5 and not #{my_linked_list_length}" if my_linked_list_length != 5 +# puts "Confirming length of the linked list." +# my_linked_list_length = my_linked_list.length +# puts "BUG: Length should be 5 and not #{my_linked_list_length}" if my_linked_list_length != 5 # find min and max -puts "Confirming min and max values in the linked list." -min = my_linked_list.find_min -puts "BUG: Min value should be 1 and not #{min}" if min != 1 -max = my_linked_list.find_max -puts "BUG: Max value should be 5 and not #{max}" if max != 6 +# puts "Confirming min and max values in the linked list." +# min = my_linked_list.find_min +# puts "BUG: Min value should be 1 and not #{min}" if min != 1 +# max = my_linked_list.find_max +# puts "BUG: Max value should be 5 and not #{max}" if max != 6 # delete value -puts "Deleting node with value 5 from the linked list." -my_linked_list.delete(5) +# puts "Deleting node with value 5 from the linked list." +# my_linked_list.delete(5) # print all elements -puts "Printing elements in the linked list:" -my_linked_list.visit +# puts "Printing elements in the linked list:" +# my_linked_list.visit # validate length -puts "Confirming length of the linked list." -my_linked_list_length = my_linked_list.length -puts "BUG: Length should be 4 and not #{my_linked_list_length}" if my_linked_list_length != 4 +# puts "Confirming length of the linked list." +# my_linked_list_length = my_linked_list.length +# puts "BUG: Length should be 4 and not #{my_linked_list_length}" if my_linked_list_length != 4 # delete value -puts "Deleting node with value 1 from the linked list." -my_linked_list.delete(1) -# print all elements -puts "Printing elements in the linked list:" -my_linked_list.visit -# validate length -puts "Confirming length of the linked list." -my_linked_list_length = my_linked_list.length -puts "BUG: Length should be 3 and not #{my_linked_list_length}" if my_linked_list_length != 3 - +# puts "Deleting node with value 1 from the linked list." +# my_linked_list.delete(1) +# # print all elements +# puts "Printing elements in the linked list:" +# my_linked_list.visit +# # validate length +# puts "Confirming length of the linked list." +# my_linked_list_length = my_linked_list.length +# puts "BUG: Length should be 3 and not #{my_linked_list_length}" if my_linked_list_length != 3 +# # find middle element puts "Confirming middle value in the linked list." middle = my_linked_list.find_middle_value -puts "BUG: Middle value should be 4 and not #{middle}" if middle != 4 - +puts "BUG: Middle value should be 3 and not #{middle}" if middle != 3 +# # reverse the linked list puts "Reversing the linked list." my_linked_list.reverse @@ -201,29 +320,29 @@ def create_cycle puts "Printing elements in the linked list:" my_linked_list.visit # verify the reversed list -puts "Verifying the reveresed linked list by calling find_nth_from_beginning method." -value = my_linked_list.find_nth_from_beginning(2) -puts "BUG: Value at index 2 should be 3 and is #{value}" if value != 3 -value = my_linked_list.find_nth_from_beginning(1) -puts "BUG: Value at index 1 should be 4 and is #{value}" if value != 4 -value = my_linked_list.find_nth_from_beginning(0) -puts "BUG: Value at index 0 should be 6 and is #{value}" if value != 6 - -# nth from the end -puts "Verifying find_nth_from_end method." -value = my_linked_list.find_nth_from_end(0) -puts "BUG: Value at index 0 from the end, should be 3 and is #{value}" if value != 3 -value = my_linked_list.find_nth_from_end(1) -puts "BUG: Value at index 1 from the end, should be 4 and is #{value}" if value != 4 -value = my_linked_list.find_nth_from_end(2) -puts "BUG: Value at index 2 from the end, should be 6 and is #{value}" if value != 6 - -# check for cycle -puts "Checking the linked list for cycle." -puts "BUG: Should not have a cycle." if my_linked_list.has_cycle - -# create cycle and then test for it -puts "Creating a cycle in the linked list." -my_linked_list.create_cycle -puts "Checking the linked list for cycle." -puts "BUG: Should not have a cycle." if !(my_linked_list.has_cycle) +# puts "Verifying the reveresed linked list by calling find_nth_from_beginning method." +# value = my_linked_list.find_nth_from_beginning(2) +# puts "BUG: Value at index 2 should be 3 and is #{value}" if value != 3 +# value = my_linked_list.find_nth_from_beginning(1) +# puts "BUG: Value at index 1 should be 4 and is #{value}" if value != 4 +# value = my_linked_list.find_nth_from_beginning(0) +# puts "BUG: Value at index 0 should be 6 and is #{value}" if value != 6 +# +# # nth from the end +# puts "Verifying find_nth_from_end method." +# value = my_linked_list.find_nth_from_end(0) +# puts "BUG: Value at index 0 from the end, should be 3 and is #{value}" if value != 3 +# value = my_linked_list.find_nth_from_end(1) +# puts "BUG: Value at index 1 from the end, should be 4 and is #{value}" if value != 4 +# value = my_linked_list.find_nth_from_end(2) +# puts "BUG: Value at index 2 from the end, should be 6 and is #{value}" if value != 6 +# +# # check for cycle +# puts "Checking the linked list for cycle." +# puts "BUG: Should not have a cycle." if my_linked_list.has_cycle +# +# # create cycle and then test for it +# puts "Creating a cycle in the linked list." +# my_linked_list.create_cycle +# puts "Checking the linked list for cycle." +# puts "BUG: Should not have a cycle." if !(my_linked_list.has_cycle) From 1dc883607de5f2f028e7494502f021889847cb67 Mon Sep 17 00:00:00 2001 From: Cynthia Cobb Date: Wed, 30 Aug 2017 21:22:56 -0700 Subject: [PATCH 2/2] all methods implemented and passing all tests --- linked_list.rb | 255 ++++++++++++++++++++++++++++--------------------- 1 file changed, 146 insertions(+), 109 deletions(-) diff --git a/linked_list.rb b/linked_list.rb index 9994998c..635556a9 100644 --- a/linked_list.rb +++ b/linked_list.rb @@ -34,8 +34,8 @@ def insert(value) # method to find if the linked list contains a node with specified value # returns true if found, false otherwise def search(value) - # puts "Not implemented" current = @head + until current.next == nil return true if current.value == value end @@ -47,10 +47,12 @@ def search(value) def find_max current = @head max = current.data + while current max = current.data if current.data > max current = current.next end + return max end @@ -59,10 +61,12 @@ def find_max def find_min current = @head min = current.data + while current.next != nil min = current.data if current.data < min current = current.next end + return min end @@ -70,10 +74,12 @@ def find_min def length length = 0 current = @head + while current length += 1 current = current.next end + return length end @@ -81,17 +87,34 @@ def length # assume indexing starts at 0 while counting to n def find_nth_from_beginning(n) current = @head + n.times do current = current.next end - # p current + 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) - puts "Not implemented" + current = @head + previous = nil + last = nil + + until value < current.data + previous = current + current.next ? current = current.next : break + end + + insert_node = Node.new(value) + + if !current.next && value > current.data + current.next = insert_node + else + insert_node.next = current + previous.next = insert_node + end end # method to print all the values in the linked list @@ -105,38 +128,27 @@ def visit # method to delete the first node found with specified value def delete(value) - # puts "Not implemented" + return if @head == nil + current = @head + @head = current.next if current.data == value previous = nil + while current.next if current.data == value - # # need to know the next node - # # set the previous node to this next node --> knowing index/position would be nice - # next_node = current.next current = current.next - previous.next = current + previous.next = current if previous break end - current = current.next previous = current + current = current.next end - # p current - # p next_node - # # p position - # current = @head - # position.times do - # p current - # current = current.next - # end - # # p current - # # current.next = next_node end # method to reverse the singly linked list # note: the nodes should be moved and not just the values in the nodes # time complex - constant - cause visiting each node once so depends on linklist size def reverse - # puts "Not implemented" current = @head previous = nil temp = current.next @@ -153,22 +165,21 @@ def reverse ## Advanced Exercises # returns the value at the middle element in the singly linked list - def find_middle_value - # puts "Not implemented" - # check input - head is nil return - # if head nex is nil return value at head - # set slow head - # set fast head next + # check input - head is nil return + # if head nex is nil return value at head - # algo steps - # while fast is not nil - # update slow next - # update falst next - ## if fast next is not nil - update fast next + # set slow head + # set fast head next - # return value at slow + # algo steps + # while fast is not nil + # update slow next + # update falst next + ## if fast next is not nil - update fast next + # return value at slow + def find_middle_value return if @head == nil return @head.data if @head.next == nil @@ -187,28 +198,53 @@ def find_middle_value # 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) - puts "Not implemented" - # want to know length - # approach one - find length - then length - n - 1 is index - # iterate through the list again to the desired index/position + return if @head == nil + + current = @head + trailing = nil + + i = 0 + + until i == n + i += 1 + current = current.next + end + + trailing = @head - # approach two - tranverse just once - # current and trailing tracking - trailing starts once current reaches the value you want, - # then when current reaches the end, the trailing count is the index from the end + while current.next + current = current.next + trailing = trailing.next + end + return trailing.data end # checks if the linked list has a cycle. A cycle exists if any node in the # linked list links to a node already visited. # returns true if a cycle is found, false otherwise. def has_cycle - # puts "Not implemented" # have a fast and node - when they reach the same position you have a cycle # two pointers/references, fast and slow, slown and fast start at head # fast moves twice as fast # if fast becomes nil - no cycle # if fast and slow same node - then true cycle + return false if !@head || !@head.next + + slow = @head + fast = @head + + while fast + slow = slow.next + fast = fast.next + + fast = fast.next if fast + + return true if fast == slow + end + + return false end # Creates a cycle in the linked list for testing purposes @@ -228,6 +264,7 @@ def create_cycle ## --- END of class definitions --- ## + # Create an object of linked list class my_linked_list = LinkedList.new() @@ -251,68 +288,68 @@ def create_cycle puts "BUG: Value at index 0 should be 1 and is #{value}" if value != 1 # print all elements -# puts "Printing elements in the linked list:" -# my_linked_list.visit +puts "Printing elements in the linked list:" +my_linked_list.visit # Insert ascending -# puts "Adding 4 in ascending order." -# my_linked_list.insert_ascending(4) -# # check newly inserted value -# puts "Checking values by calling find_nth_from_beginning method." -# value = my_linked_list.find_nth_from_beginning(2) -# puts "BUG: Value at index 2 should be 4 and is #{value}" if value != 4 -# value = my_linked_list.find_nth_from_beginning(3) -# puts "BUG: Value at index 3 should be 5 and is #{value}" if value != 5 -# value = my_linked_list.find_nth_from_beginning(1) -# puts "BUG: Value at index 1 should be 3 and is #{value}" if value != 3 +puts "Adding 4 in ascending order." +my_linked_list.insert_ascending(4) +# check newly inserted value +puts "Checking values by calling find_nth_from_beginning method." +value = my_linked_list.find_nth_from_beginning(2) +puts "BUG: Value at index 2 should be 4 and is #{value}" if value != 4 +value = my_linked_list.find_nth_from_beginning(3) +puts "BUG: Value at index 3 should be 5 and is #{value}" if value != 5 +value = my_linked_list.find_nth_from_beginning(1) +puts "BUG: Value at index 1 should be 3 and is #{value}" if value != 3 # Insert ascending -# puts "Adding 6 in ascening order." -# my_linked_list.insert_ascending(6) +puts "Adding 6 in ascening order." +my_linked_list.insert_ascending(6) # print all elements -# puts "Printing elements in the linked list:" -# my_linked_list.visit +puts "Printing elements in the linked list:" +my_linked_list.visit # vaidate length -# puts "Confirming length of the linked list." -# my_linked_list_length = my_linked_list.length -# puts "BUG: Length should be 5 and not #{my_linked_list_length}" if my_linked_list_length != 5 +puts "Confirming length of the linked list." +my_linked_list_length = my_linked_list.length +puts "BUG: Length should be 5 and not #{my_linked_list_length}" if my_linked_list_length != 5 # find min and max -# puts "Confirming min and max values in the linked list." -# min = my_linked_list.find_min -# puts "BUG: Min value should be 1 and not #{min}" if min != 1 -# max = my_linked_list.find_max -# puts "BUG: Max value should be 5 and not #{max}" if max != 6 +puts "Confirming min and max values in the linked list." +min = my_linked_list.find_min +puts "BUG: Min value should be 1 and not #{min}" if min != 1 +max = my_linked_list.find_max +puts "BUG: Max value should be 5 and not #{max}" if max != 6 # delete value -# puts "Deleting node with value 5 from the linked list." -# my_linked_list.delete(5) +puts "Deleting node with value 5 from the linked list." +my_linked_list.delete(5) # print all elements -# puts "Printing elements in the linked list:" -# my_linked_list.visit +puts "Printing elements in the linked list:" +my_linked_list.visit # validate length -# puts "Confirming length of the linked list." -# my_linked_list_length = my_linked_list.length -# puts "BUG: Length should be 4 and not #{my_linked_list_length}" if my_linked_list_length != 4 +puts "Confirming length of the linked list." +my_linked_list_length = my_linked_list.length +puts "BUG: Length should be 4 and not #{my_linked_list_length}" if my_linked_list_length != 4 # delete value -# puts "Deleting node with value 1 from the linked list." -# my_linked_list.delete(1) -# # print all elements -# puts "Printing elements in the linked list:" -# my_linked_list.visit -# # validate length -# puts "Confirming length of the linked list." -# my_linked_list_length = my_linked_list.length -# puts "BUG: Length should be 3 and not #{my_linked_list_length}" if my_linked_list_length != 3 -# +puts "Deleting node with value 1 from the linked list." +my_linked_list.delete(1) +# print all elements +puts "Printing elements in the linked list:" +my_linked_list.visit +# validate length +puts "Confirming length of the linked list." +my_linked_list_length = my_linked_list.length +puts "BUG: Length should be 3 and not #{my_linked_list_length}" if my_linked_list_length != 3 + # find middle element puts "Confirming middle value in the linked list." middle = my_linked_list.find_middle_value -puts "BUG: Middle value should be 3 and not #{middle}" if middle != 3 -# +puts "BUG: Middle value should be 4 and not #{middle}" if middle != 4 + # reverse the linked list puts "Reversing the linked list." my_linked_list.reverse @@ -320,29 +357,29 @@ def create_cycle puts "Printing elements in the linked list:" my_linked_list.visit # verify the reversed list -# puts "Verifying the reveresed linked list by calling find_nth_from_beginning method." -# value = my_linked_list.find_nth_from_beginning(2) -# puts "BUG: Value at index 2 should be 3 and is #{value}" if value != 3 -# value = my_linked_list.find_nth_from_beginning(1) -# puts "BUG: Value at index 1 should be 4 and is #{value}" if value != 4 -# value = my_linked_list.find_nth_from_beginning(0) -# puts "BUG: Value at index 0 should be 6 and is #{value}" if value != 6 -# -# # nth from the end -# puts "Verifying find_nth_from_end method." -# value = my_linked_list.find_nth_from_end(0) -# puts "BUG: Value at index 0 from the end, should be 3 and is #{value}" if value != 3 -# value = my_linked_list.find_nth_from_end(1) -# puts "BUG: Value at index 1 from the end, should be 4 and is #{value}" if value != 4 -# value = my_linked_list.find_nth_from_end(2) -# puts "BUG: Value at index 2 from the end, should be 6 and is #{value}" if value != 6 -# -# # check for cycle -# puts "Checking the linked list for cycle." -# puts "BUG: Should not have a cycle." if my_linked_list.has_cycle -# -# # create cycle and then test for it -# puts "Creating a cycle in the linked list." -# my_linked_list.create_cycle -# puts "Checking the linked list for cycle." -# puts "BUG: Should not have a cycle." if !(my_linked_list.has_cycle) +puts "Verifying the reveresed linked list by calling find_nth_from_beginning method." +value = my_linked_list.find_nth_from_beginning(2) +puts "BUG: Value at index 2 should be 3 and is #{value}" if value != 3 +value = my_linked_list.find_nth_from_beginning(1) +puts "BUG: Value at index 1 should be 4 and is #{value}" if value != 4 +value = my_linked_list.find_nth_from_beginning(0) +puts "BUG: Value at index 0 should be 6 and is #{value}" if value != 6 + +# nth from the end +puts "Verifying find_nth_from_end method." +value = my_linked_list.find_nth_from_end(0) +puts "BUG: Value at index 0 from the end, should be 3 and is #{value}" if value != 3 +value = my_linked_list.find_nth_from_end(1) +puts "BUG: Value at index 1 from the end, should be 4 and is #{value}" if value != 4 +value = my_linked_list.find_nth_from_end(2) +puts "BUG: Value at index 2 from the end, should be 6 and is #{value}" if value != 6 + +# check for cycle +puts "Checking the linked list for cycle." +puts "BUG: Should not have a cycle." if my_linked_list.has_cycle + +# create cycle and then test for it +puts "Creating a cycle in the linked list." +my_linked_list.create_cycle +puts "Checking the linked list for cycle." +puts "BUG: Should not have a cycle." if !(my_linked_list.has_cycle)