mirror of
https://github.com/TheAlgorithms/Ruby
synced 2025-01-27 19:58:06 +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
|
class DoubleList
|
||||||
include Enumerable
|
# Initialize your data structure here.
|
||||||
attr_accessor :head, :tail
|
attr_reader :head, :tail, :size
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
@head = nil
|
@head = nil
|
||||||
@tail = nil
|
@tail = nil
|
||||||
|
@size = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
def insert_tail(value)
|
# Get the value of the index-th node in the linked list.
|
||||||
new_node = Node.new(value)
|
# If the index is invalid, return -1.
|
||||||
if @head.nil?
|
def get(index)
|
||||||
@head = new_node
|
return -1 if @head.nil?
|
||||||
@tail = new_node
|
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
|
else
|
||||||
@tail.next = new_node
|
iter = @tail
|
||||||
new_node.prev = @tail
|
cnt = @size - 1
|
||||||
@tail = new_node
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
def insert_head(value)
|
def insert(node, new_node)
|
||||||
new_node = Node.new(value)
|
new_node.prev = node
|
||||||
if @head.nil?
|
new_node.next = node.next
|
||||||
@head = new_node
|
node.next.prev = new_node
|
||||||
@tail = new_node
|
node.next = new_node
|
||||||
else
|
@size += 1
|
||||||
new_node.next = @head
|
end
|
||||||
@head.prev = new_node
|
|
||||||
@head = new_node
|
# 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
|
||||||
end
|
end
|
||||||
|
|
||||||
def delete_tail
|
def remove(node)
|
||||||
until @tail.nil?
|
if node == @head
|
||||||
@tail = @tail.prev
|
|
||||||
@tail.next = nil unless @tail.nil?
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def delete_head
|
|
||||||
until @head.nil?
|
|
||||||
@head = @head.next
|
@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
|
end
|
||||||
|
@size -= 1
|
||||||
end
|
end
|
||||||
|
|
||||||
def each
|
def print_values(head = @head)
|
||||||
return if @head.nil?
|
print "#{head.val} --> "
|
||||||
|
if head.next.nil?
|
||||||
current = @head
|
puts("nil\n")
|
||||||
until current.nil?
|
return
|
||||||
yield current.value
|
else
|
||||||
current = current.next
|
print_values(head.next)
|
||||||
end
|
end
|
||||||
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
|
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…
Add table
Reference in a new issue