如何在Ruby中反转链表
在下面的例子中,我不明白链表是如何颠倒的如何在Ruby中反转链表,ruby,linked-list,Ruby,Linked List,在下面的例子中,我不明白链表是如何颠倒的 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_n
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)
如果我只返回current\u head
,我会得到99->37->nil
,这是有意义的,因为99
将是下一个节点。返回下一行
list.next_node = previous
抛出错误,因为print_values
方法无法打印nil
的值。我不明白是什么在颠倒清单。如果有人能给我解释一下,我将不胜感激
# 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
第一次进入反向列表法
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
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
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
第二次进入反向列表法
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
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
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
最后一次进入反向列表方法
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
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
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
顺便说一句,在ruby语言(以及所有带有垃圾收集器的语言)中,链表并不是一种常见的做法,通常有一个类(例如Array)具有您可能需要的所有功能和灵活性。下面是我编的一个小可视化
^
指向列表的开头。在递归的每一级,它的右箭头都被“旋转”为从右边的元素指向左边的元素。继续,直到出现右箭头(指向非零)。如果右箭头指向零,则返回当前头部
previous
↓
nil 12 -> 99 -> 37 -> nil
^
previous
↓
nil <- 12 99 -> 37 -> nil
^
previous
↓
nil <- 12 <- 99 37 -> nil
^
nil <- 12 <- 99 <- 37
^
上一个
↓
零12->99->37->零
^
以前的
↓
零37->零
^
以前的
↓
nil如果有人希望在不使用递归的情况下执行此操作,那么这里有一个简单的解决方案
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]
只需手动运行算法。用笔和纸。跟踪节点的状态。你会明白的。这没有回答问题,是吗?@SergioTulentsev你睡过吗?@WandMaker:我正要:)你说得对,没有。我没有正确理解这个问题是的,我理解。我这么做只是因为我必须这么做,这是我课程的一部分。他们甚至告诉我们,这个问题很少使用,但理解起来很重要,因为这是一个常见的面试问题。安东尼,它有用吗?:)现在你看到那里发生了什么了吗?很好的可视化,这并不是说我不理解指针是如何被重新排列的,我不理解反向列表代码在做什么。你们都给出了很好的答案!非常感谢。在阅读皮尔斯的答案时看到你的答案真的很有帮助。一旦我理解了它,我决定尝试一个迭代的解决方案,而不是递归,只是为了巩固东西。