Merge pull request #84 from TheAlgorithms/improve-doubly-linked-list

[Data structures] Add circular linked list and improve singly/doubly linked list
This commit is contained in:
Vitor Oliveira 2021-02-13 10:33:04 -08:00 committed by GitHub
commit bc96d1c4ea
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 311 additions and 82 deletions

View file

@ -11,8 +11,9 @@
* [Postorder Traversal](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/binary_trees/postorder_traversal.rb)
* [Preorder Traversal](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/binary_trees/preorder_traversal.rb)
* Linked Lists
* [Double List](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/linked_lists/double_list.rb)
* [Single List](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/linked_lists/single_list.rb)
* [Circular Linked List](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/linked_lists/circular_linked_list.rb)
* [Doubly Linked List](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/linked_lists/doubly_linked_list.rb)
* [Singly Linked List](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/linked_lists/singly_linked_list.rb)
* Queues
* [Queue](https://github.com/TheAlgorithms/Ruby/blob/master/data_structures/queues/queue.rb)
* Stacks

View file

@ -0,0 +1,109 @@
# Define a node for the list
class Node
attr_accessor :value, :next
def initialize(value)
@value = value
@next = nil
end
end
# Class for circular linked list (last node points to the head node)
class CircularList
attr_reader :head
def initialize
@head = nil
end
def insert_tail(value)
newNode = Node.new(value)
if @head.nil?
@head = newNode
@head.next = @head
else
tempNode = @head
tempNode = tempNode.next while tempNode.next != @head
newNode.next = @head
tempNode.next = newNode
end
end
def insert_head(value)
newNode = Node.new(value)
if @head.nil?
@head = newNode
@head.next = head
else
tempNode = @head
tempNode = tempNode.next while tempNode.next != @head
newNode.next = @head
tempNode.next = newNode
@head = newNode
end
end
def print_list
print '['
unless @head.nil?
printNode = @head
while printNode.next != @head
print printNode.value.to_s
print ', '
printNode = printNode.next
end
print printNode.value
end
print ']'
puts(STDOUT.flush)
end
def delete_head
return if @head.nil?
if @head.next != @head
newHead = @head.next
tempNode = newHead
tempNode = tempNode.next while tempNode.next != @head
tempNode.next = newHead
@head = newHead
elsif !@head.nil? && (@head.next == @head)
@head = nil
end
end
def delete_tail
return if @head.nil?
if @head.next != @head
tempNode = @head
tempNode = tempNode.next while tempNode.next.next != @head
tempNode.next = @head
elsif !@head.nil? && (@head.next == @head)
@head = nil
end
end
def is_empty
@head.nil?
end
end
obj = CircularList.new
obj.insert_tail(1)
obj.insert_tail(2)
obj.insert_tail(3)
obj.insert_tail(4)
obj.insert_tail(5)
obj.print_list
obj.insert_head(6)
obj.print_list
obj.delete_tail
obj.print_list
obj.delete_head
obj.print_list

View file

@ -1,78 +0,0 @@
# Define a node in the list
class Node
attr_accessor :value, :next, :prev
def initialize(value)
@value = value
@next = nil
@prev = nil
end
end
# A Class for double linked lists (each element links to the next one, and to the previous one)
class DoubleList
include Enumerable
attr_accessor :head, :tail
def initialize
@head = nil
@tail = nil
end
def insert_tail(value)
new_node = Node.new(value)
if @head.nil?
@head = new_node
@tail = new_node
else
@tail.next = new_node
new_node.prev = @tail
@tail = new_node
end
end
def insert_head(value)
new_node = Node.new(value)
if @head.nil?
@head = new_node
@tail = new_node
else
new_node.next = @head
@head.prev = new_node
@head = new_node
end
end
def delete_tail
until @tail.nil?
@tail = @tail.prev
@tail.next = nil unless @tail.nil?
end
end
def delete_head
until @head.nil?
@head = @head.next
@head.prev = nil unless @head.nil?
end
end
def each
return if @head.nil?
current = @head
until current.nil?
yield current.value
current = current.next
end
end
def print_list
# the to_a method is from Enumerable, will call each to get the values, and return an array
puts '[' + to_a.join(', ') + ']'
end
def empty?
@head.nil?
end
end

View file

@ -0,0 +1,179 @@
class DoublyLinkedList
# Initialize the data structure here.
attr_reader :head, :tail, :size
def initialize
@head = nil
@tail = nil
@size = 0
end
# Get the value of the index-th node in the linked list.
# If the index is invalid, return -1.
def get(index)
return -1 if @head.nil?
return -1 if index > @size - 1
if index < @size - index
iter = @head
cnt = 0
until iter.nil?
return iter.val if cnt == index
iter = iter.next
cnt += 1
end
else
iter = @tail
cnt = @size - 1
until iter.nil?
return iter.val if cnt == index
iter = iter.prev
cnt -= 1
end
end
-1
end
# Add a node of value val before the first element of the linked list.
# After the insertion, the new node will be the first node of the linked list.
def insert_head(val)
node = Node.new(val, nil, @head)
@tail = node unless @head
@head.prev = node if @head
@head = node
@size += 1
end
# Append a node of value val to the last element of the linked list.
def insert_tail(val)
return insert_head(val) unless @head
node = Node.new(val, @tail, nil)
@tail.next = node
@tail = node
@size += 1
end
# Add a node of value val before the index-th node in the linked list.
# If index equals to the length of linked list, the node will be appended
# to the end of linked list. If index is greater than the length, the node
# will not be inserted.
def add_at_index(index, val)
case index
when 0 then insert_head(val)
when @size then insert_tail(val)
when 1...@size
if index < @size - index
iter = @head
cnt = 0
until iter.nil?
return insert(iter, Node.new(val)) if cnt == index - 1
iter = iter.next
cnt += 1
end
else
iter = @tail
cnt = @size - 1
until iter.nil?
return insert(iter, Node.new(val)) if cnt == index - 1
iter = iter.prev
cnt -= 1
end
end
end
end
def insert(node, new_node)
new_node.prev = node
new_node.next = node.next
node.next.prev = new_node
node.next = new_node
@size += 1
end
# Delete the index-th node in the linked list, if the index is valid.
def delete_at_index(index)
case index
when 0
return unless @head
return @head, @tail, @size = nil, nil, 0 if @size == 1
remove(@head)
when @size - 1
remove(@tail)
when 1...@size - 1
if index < @size - index
iter = @head
cnt = 0
until iter.nil?
return remove(iter) if cnt == index
iter = iter.next
cnt += 1
end
else
iter = @tail
cnt = @size - 1
until iter.nil?
return remove(iter) if cnt == index
iter = iter.prev
cnt -= 1
end
end
end
end
def remove(node)
if node == @head
@head = @head.next
@head.prev = nil
elsif node == @tail
@tail = tail.prev
@tail.next = nil
else
node.prev.next = node.next
node.next.prev = node.prev
end
@size -= 1
end
def print_values(head = @head)
print "#{head.val} --> "
if head.next.nil?
puts("nil\n")
return
else
print_values(head.next)
end
end
end
class Node
attr_accessor :val, :prev, :next
def initialize(val = nil, prev = nil, next_ = nil)
@val = val
@prev = prev
@next = next_
end
end
obj = DoublyLinkedList.new
obj.get(1)
obj.insert_head(2)
obj.print_values
obj.insert_tail(3)
obj.print_values
obj.add_at_index(3, 5)
obj.print_values
obj.delete_at_index(1)
obj.print_values

View file

@ -1,5 +1,6 @@
# Define a node in the list
class Node
# Initialize the data structure here.
attr_accessor :value, :next
def initialize(value)
@ -9,8 +10,7 @@ class Node
end
# A Class for single linked lists (each element links to the next one, but not to the previous one)
class SingleList
class SinglyLinkedList
include Enumerable
attr_accessor :head
@ -74,3 +74,21 @@ class SingleList
@head.nil?
end
end
obj = SinglyLinkedList.new
obj.insert_head(1)
obj.insert_head(2)
obj.insert_head(3)
obj.insert_head(4)
obj.insert_head(5)
obj.print_list
obj.insert_tail(6)
obj.print_list
obj.delete_head
obj.print_list
obj.delete_tail
obj.print_list