Removing an Item from a LinkedList - ruby

I am trying to make a LinkedList assignment on ruby and was facing difficulties to do the remove method, so I searched in google and got the code from the remove method.
What I can't understand is the logic behind it, I can't understand how it works, how it works the logic to delete it.
class Node
attr_accessor :value, :next_node
def initialize(value, next_node = nil)
#value = value
#next_node = next_node
end
end
class LinkedList
def add(number)
new_node = Node.new(number)
if #head.nil?
#head = new_node
#tail = new_node
else
#tail.next_node = new_node
#tail = new_node
end
end
def get(index)
#your code here
node = #head
while index > 0 && node
node = node.next_node
index -= 1
end
node.value
end
def add_at (index, number)
if #head.nil?
#head = Node.new(number)
#tail = Node.new(number)
else
first = #head
index -= 1
while index > 0 && first
first = first.next_node
index -= 1
end
old_next = first.next_node
first.next_node = Node.new(number)
first.next_node.next_node = old_next
end
end
def remove (index)
node = #head
index -= 1
while index > 0 && node
node = node.next_node
index -= 1
end
node.next_node = node.next_node.next_node
end
end

Related

How to reverse a linked list in Ruby

In the mutation example below, I don't understand how the linked list is reversed.
class LinkedListNode
attr_accessor :value, :next_node
def initialize(value, next_node=nil)
#value = value
#next_node = next_node
end
end
def print_values(list_node)
print "#{list_node.value} --> "
if list_node.next_node.nil?
print "nil\n"
return
else
print_values(list_node.next_node)
end
end
def reverse_list(list, previous=nil)
current_head = list.next_node
list.next_node = previous
if current_head
reverse_list(current_head, list)
else
list
end
end
node1 = LinkedListNode.new(37)
node2 = LinkedListNode.new(99, node1)
node3 = LinkedListNode.new(12, node2)
print_values(node3)
puts "-------"
revlist = reverse_list(node3)
print_values(revlist)
If I just return current_head, I get 99->37->nil, which makes sense because 99 would be next_node. Returning the next line,
list.next_node = previous
throws an error because print_values method can't print the value for nil. I'm not understanding what is reversing the list. If anyone could explain this to me, I would appreciate it.
Here's a little visualization I made up.
^ points to head of the list. At each level of recursion, its right arrow is "turned" to point from element on the right to element on the left. Proceed until there is a right arrow (pointing to a non-nil). If right arrow points to nil, return the current head.
previous
↓
nil 12 -> 99 -> 37 -> nil
^
previous
↓
nil <- 12 99 -> 37 -> nil
^
previous
↓
nil <- 12 <- 99 37 -> nil
^
nil <- 12 <- 99 <- 37
^
# Create a LinkedListNode instance with value 36
node1 = LinkedListNode.new(37)
# Create a LinkedListNode instance which next value is node1
node2 = LinkedListNode.new(99, node1)
# node2 -> node1
# Create a LinkedListNode instance which next value is node2
node3 = LinkedListNode.new(12, node2)
# node3 -> node2 -> node1
print_values(node3)
# 12 -> 99 -> 37
Fist pass into reverse_list method
reverse_list(node3)
def reverse_list(list, previous=nil)
# set current_head to node2
current_head = list.next_node
# Change node3.next_node node2-->nil
list.next_node = previous
if current_head
# reverse_list(node2, node3)
reverse_list(current_head, list)
else
list
end
end
Second pass into reverse_list method
reverse_list(node2, node3)
def reverse_list(list, previous=nil)
# set current_head to node1
current_head = list.next_node
# Change node2.next_node node1-->node3
list.next_node = previous
if current_head
# reverse_list(node1, node2)
reverse_list(current_head, list)
else
list
end
end
last pass into reverse_list method
reverse_list(node1, node2)
def reverse_list(list, previous=nil)
# set current_head to nil
current_head = list.next_node
# Change node1.next_node nil-->node2
list.next_node = previous
if current_head
reverse_list(current_head, list)
else
# The end, return node1
list
end
end
By the way linked list is not a common practice in the ruby languages (and all the languages with a garbage collector), there is generally a class (such as Array for example) which have all the functionalities and flexibility you may need.
Here is a simple solution if someone is looking to do this without recursion
class Node
attr_accessor :value, :next
def initialize(value, next_node)
#value = value
#next = next_node
end
end
class LinkedList
attr_accessor :head, :tail
def add(value)
if(#head.nil?)
#head = Node.new(value, nil)
#tail = #head
else
#tail.next = Node.new(value, nil)
#tail = #tail.next
end
end
def reverse(list)
return nil if list.nil?
prev = nil
curr = list.head
while(curr != nil)
temp = curr.next
curr.next = prev
prev = curr
curr = temp
end
list.head = prev
list
end
def display(list)
return nil if list.nil?
curr = list.head
arr = []
while(curr != nil)
arr.push(curr.value)
curr = curr.next
end
p arr
end
end
list = LinkedList.new()
list.add(1)
list.add(2)
list.add(3)
list.display(list) #list before reversing [1,2,3]
list.display(list.reverse(list)) #list after reversing [3,2,1]

How to remove object in Ruby

I've implemented Binary search tree in ruby, and now I need to clean whole structure but I can't find any way to do that.
def post_order_clean(node)
if node.left != nil
post_order_clean(node.left)
end
if node.right != nil
post_order_clean(node.right)
end
node = nil
end
But when i do sth like that:
example = [4,6,9,5,7,3,1]
tree = BST::BinaryTree.new(example)
tree.clean
puts tree.root.value
It still prints out 4 as a root value.
How can I clean the tree with post-order traversing method?
Edit:
Just like #Cary Swoveland mentioned:
.. successively remove nodes (together with arcs directed to the node) that have no arcs directed to other nodes.
That's my point.
I did this solution for insert and remove:
class TreeNode
attr_accessor :val, :left, :right
def initialize(val)
#val = val
#left, #right = nil, nil
end
def insert(v)
side = (v <= val ? :left : :right)
if send(side)
send(side).insert(v)
else
send("#{side}=", TreeNode.new(v))
end
end
def delete(v)
if v < val
self.left = self.left ? self.left.delete(v) : nil
elsif v > val
self.right = self.right ? self.right.delete(v) : nil
else
if self.left.nil?
return self.right
elsif self.right.nil?
return self.left
end
min = self.right
min = min.left while !min.left.nil?
self.val = min.val
self.right = self.right.delete(self.val)
end
self
end
end

Sum of positive elements in linked list

I need to make program, but i can't finish it and get into mess with methods.
The aim is to find the sum of all positive of elements and add it in the end. I am just started teach classes and methods.
How can I make the sum of all positive elements in my final array?
Here is my code:
class Node
attr_accessor :value, :next_node
def initialize val,next_in_line
#value = val
#next_nodex = next_in_line
puts "Initialized a Node with value: " + value.to_s
end
end
class LinkedList
def initialize val
#head = Node.new(val,nil)
end
def add(value)
current = #head
while current.next_node != nil
current = current.next_node
end
current.next_node = Node.new(value,nil)
self
end
def delete(val)
current = #head
if current.value == val
#head = #head.next_node
else
current = #head
while (current != nil) && (current.next_node != nil) && ((current.next_node).value != val)
current = current.next_node
end
if (current != nil) && (current.next_node != nil)
current.next_node = (current.next_node).next_node
end
end
end
def display
current = #head
full_list = []
while current.next_node != nil
full_list += [current.value.to_s]
current = current.next_node
end
full_list += [current.value.to_s]
puts full_list.join(" ")
end
def sum
end
end
puts "\n"
list = [*-99..99].shuffle
ll = LinkedList.new(list[0])
(1..9).each do |i|
ll.add(list[i])
end
puts "\nDo you want item to add? '1' - yes '0' - no"
adding = gets.to_i
puts "\n"
if adding == 1
ll.add(list[10])
end
puts "\nDisplaying Linked List:"
ll.display
puts "\nDo you want to delete item? '1' - yes '0' - no"
deleting = gets.to_i
if deleting == 1
puts "Type in and delete item and then display the linked list:"
deleteInt = gets.to_i
ll.delete(deleteInt)
end
puts ll.display
puts "\nThe sum of all positive elements"
ll.sum
Firstly, You have mistype in Node.initialize method - #next_nodex should be #next_node i think. Secondly, don't use puts 2 times: puts ll.display at the end. To add in array preferably use << symbol.
Another thing, i can't see any concept difference between display and sum methods, except one condition. According to this, it should be like:
def sum
current = #head
sum = 0
while current.next_node != nil
sum += current.value if current.value > 0
current = current.next_node
end
sum += current.value if current.value > 0
sum
end
or with dry:
def full_list
current = #head
full_list = []
while current.next_node != nil
full_list << current.value
current = current.next_node
end
full_list << current.value
full_list
end
def display
puts full_list.join(' ')
end
def sum
full_list.keep_if { |x| x > 0 }.reduce(:+)
end
All code

Sorted Linked List in Python

I'm having a bit of trouble figuring out how to sort a Singly Linked list in Python. I've figured out how to create a linked list and push data onto it but how do I push it in a sorted format (not sorting after all the data is pushed onto it) or just sorting it in any way?
Objective
Create a sorted singly linked list of numbers based upon user input.
Program logic:
Ask for a number, add that number to the list in sorted position, print the list.
Repeat until they enter -1 for the number.
Current Code
#!/usr/bin/env python
class node:
def __init__(self):
self.data = None # contains the data
self.next = None # contains the reference to the next node
class linked_list:
def __init__(self):
self.cur_node = None
def add_node(self, data):
new_node = node() # create a new node
new_node.data = data
new_node.next = self.cur_node # link the new node to the 'previous' node.
self.cur_node = new_node # set the current node to the new one.
def list_print(self):
node = self.cur_node # cant point to ll!
while node:
print(node.data)
node = node.next
def main():
ll = linked_list()
num=int(input("Enter a num to push onto the list, -1 to stop: "))
while num!=-1:
data=num
ll.add_node(data)
num=int(input("Enter a num to push onto the list, -1 to stop: "))
print("\n")
ll.list_print()
main()
I'm really stuck here. Thank you in advance for any help!
This should do it:
class Node:
def __init__(self):
self.data = None
self.next = None
class LinkedList:
def __init__(self):
self.head = None
def addNode(self, data):
curr = self.head
if curr is None:
n = Node()
n.data = data
self.head = n
return
if curr.data > data:
n = Node()
n.data = data
n.next = curr
self.head = n
return
while curr.next is not None:
if curr.next.data > data:
break
curr = curr.next
n = Node()
n.data = data
n.next = curr.next
curr.next = n
return
def __str__(self):
data = []
curr = self.head
while curr is not None:
data.append(curr.data)
curr = curr.next
return "[%s]" %(', '.join(str(i) for i in data))
def __repr__(self):
return self.__str__()
def main():
ll = LinkedList()
num = int(input("Enter a number: "))
while num != -1:
ll.addNode(num)
num = int(input("Enter a number: "))
c = ll.head
while c is not None:
print(c.data)
c = c.next
Gives
>>> main()
Enter a number: 5
Enter a number: 3
Enter a number: 2
Enter a number: 4
Enter a number: 1
Enter a number: -1
1
2
3
4
5
class Node:
def __init__(self, data):
self.data = int(data)
self.next = None
class LinkedList:
def __init__(self):
self.head = None
def asc_ordered_list(self, data):
new_node = Node(data)
if self.head is None:
self.head = new_node
return
temp = self.head
if temp.data > data:
new_node.next = temp
self.head = new_node
return
while temp.next:
if temp.next.data > data:
break
temp = temp.next
new_node.next = temp.next
temp.next = new_node
def desc_ordered_list(self, data):
new_node = Node(data)
if self.head is None:
self.head = new_node
return
temp = self.head
if data > temp.data:
new_node.next = temp
self.head = new_node
return
while temp.next:
if temp.data > data and temp.next.data < data:
break
temp = temp.next
new_node.next = temp.next
temp.next = new_node
def display_list(self):
temp = self.head
while temp is not None:
print("data = {0}".format(temp.data))
temp = temp.next
if __name__ == "__main__":
llist = LinkedList()
llist.desc_ordered_list(8)
llist.desc_ordered_list(3)
llist.desc_ordered_list(1)
llist.desc_ordered_list(4)
llist.desc_ordered_list(5)
llist.desc_ordered_list(7)
llist.desc_ordered_list(6)
llist.desc_ordered_list(2)
llist.display_list()
4 years later, but I think that is easier in this way
def append(self, value):
new_node = Node(value)
if self.head is None:
self.head = new_node
else:
current = self.head
while current is not None and current.value <= value:
previous = current
current = current.next
if current is self.head:
aux = self.head
self.head = new_node
new_node.next = aux
else:
previous.next = new_node
new_node.next = current
self.size += 1
class Solution:
def sortList(self,node):
if(node is None):
return
temp=node
while(temp!=None):
i=temp.next
while(i!=None):
if(temp.data>i.data):
n=i.data
i.data=temp.data
temp.data=n
i=i.next
temp=temp.next
I thought this was a bit shorter and easier
class Node:
def __init__(self, data, _next=None):
self.data = data
self.next = _next
def main():
nodes = []
num = int(input("Enter number: "))
while num != -1:
nodes.append(Node(num))
num = int(input("Enter number: "))
# If list is empty then just end function
if len(nodes) == 0:
return
# Let python do the sorting
nodes = sorted(nodes, key=lambda node: node.data)
# Link the nodes together and print them while you're at it
for i in range(len(nodes) - 1):
nodes[i].next = nodes[i + 1]
print(nodes[i].data)
# We need to print the last node
print(nodes[-1].data)

Having Difficulty to Understand Variables/Pointers on Ruby LinkedList Implementation

I created a singly LinkedList class with ruby.
Everything went well till trying to reverse the linked list.
It does not reverse linkedlist by this method, but when I add
#head.next = nil
after left_tmp = #head in reverse method, it just works fine.
I couldn't figure out why it works when I add that, does anyone have the explanation?
BTW I am fairly new to ruby, so please don't hesitate to tell me if there are some other things that are not "Good Practice in Ruby".
Here is classes and relevant methods:
class LlNode
attr_reader :data
attr_accessor :next
def initialize(val=nil)
#data = val
#next = nil
end
def to_s
"node_data=#{#data}"
end
end
class LinkedList
def initialize
#list = []
#head = LlNode.new
end
def insert(val)
n = LlNode.new val
# List is empty
if is_empty?
#head = n
else
n.next = #head
#head = n
end
self
end
def reverse
return if is_empty? or #head.next.nil?
curr = #head.next
right_tmp = curr.next
left_tmp = #head
while curr != nil
curr.next = left_tmp
left_tmp = curr
curr = right_tmp
right_tmp = right_tmp.next unless right_tmp.nil?
end
#head = left_tmp
end
end
When you're reversing a linked list, the first node becomes the last. In a singly-linked list, the last node's next pointer points to null. #head, which is initially your first node becomes the last. That's why you add the #head.next = nil.
Edit: Simulating a dry-run to better explain the problem
Assume two nodes in the linked list: 1->2
curr = #head.next (2)
right_tmp = curr.next (nil)
left_tmp = #head (1)
First iteration of the while loop:
curr.next = left_tmp ( 1 <-> 2)
left_tmp = curr (2)
curr = right_tmp (nil)
right_tmp = right_tmp.next unless right_tmp.nil? (nil)
There is no second iteration since curr == nil
Now:
#head = left_tmp (#head points to '2')
Final linked list state is:
1 <-> 2

Resources