mirror of
https://github.com/TheAlgorithms/Ruby
synced 2025-01-13 08:01:03 +01:00
Improve doubly linked list
This commit is contained in:
parent
8607abde16
commit
1511265825
1 changed files with 159 additions and 57 deletions
|
@ -1,78 +1,180 @@
|
|||
# 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
|
||||
# Initialize your data structure here.
|
||||
attr_reader :head, :tail, :size
|
||||
|
||||
def initialize
|
||||
@head = nil
|
||||
@tail = nil
|
||||
@size = 0
|
||||
end
|
||||
|
||||
def insert_tail(value)
|
||||
new_node = Node.new(value)
|
||||
if @head.nil?
|
||||
@head = new_node
|
||||
@tail = new_node
|
||||
# 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
|
||||
@tail.next = new_node
|
||||
new_node.prev = @tail
|
||||
@tail = new_node
|
||||
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 add_at_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 add_at_tail(val)
|
||||
return add_at_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 add_at_head(val)
|
||||
when @size then add_at_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
|
||||
# else put "illegal input"
|
||||
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
|
||||
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
|
||||
# else put "illegal input"
|
||||
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?
|
||||
def remove(node)
|
||||
if node == @head
|
||||
@head = @head.next
|
||||
@head.prev = nil unless @head.nil?
|
||||
@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 each
|
||||
return if @head.nil?
|
||||
|
||||
current = @head
|
||||
until current.nil?
|
||||
yield current.value
|
||||
current = current.next
|
||||
def print_values(head = @head)
|
||||
print "#{head.val} --> "
|
||||
if head.next.nil?
|
||||
puts("nil\n")
|
||||
return
|
||||
else
|
||||
print_values(head.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
|
||||
|
||||
class Node
|
||||
attr_accessor :val, :prev, :next
|
||||
|
||||
def initialize(val = nil, prev = nil, next_ = nil)
|
||||
@val = val
|
||||
@prev = prev
|
||||
@next = next_
|
||||
end
|
||||
end
|
||||
|
||||
obj = DoubleList.new
|
||||
param_1 = obj.get(1)
|
||||
obj.add_at_head(2)
|
||||
obj.print_values
|
||||
|
||||
obj.add_at_tail(3)
|
||||
obj.print_values
|
||||
|
||||
obj.add_at_index(3, 5)
|
||||
obj.print_values
|
||||
|
||||
obj.delete_at_index(1)
|
||||
obj.print_values
|
||||
|
|
Loading…
Reference in a new issue