【问题标题】:How to reverse a linked list in Ruby如何在 Ruby 中反转链表
【发布时间】:2015-12-23 20:57:50
【问题描述】:

在下面的突变示例中,我不明白链表是如何反转的。

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_head,我会得到99->37->nil,这是有道理的,因为99 将是next_node。返回下一行,

list.next_node = previous

由于print_values 方法无法打印nil 的值而引发错误。我不明白什么是颠倒列表。如果有人可以向我解释这一点,我将不胜感激。

【问题讨论】:

  • 手动运行算法即可。用笔和纸。跟踪节点的状态。你会看到的。

标签: ruby linked-list


【解决方案1】:

这是我编造的一个小可视化。

^ 指向列表的头部。在递归的每一级,它的右箭头“转向”以从右边的元素指向左边的元素。继续直到有一个右箭头(指向非零)。如果右箭头指向 nil,则返回当前头部。

previous
↓
nil    12 -> 99 -> 37 -> nil
       ^

       previous
       ↓ 
nil <- 12       99 -> 37 -> nil
                ^

             previous
             ↓
nil <- 12 <- 99       37 -> nil
                      ^         

nil <- 12 <- 99 <- 37 
                   ^                            

【讨论】:

  • 安东尼,有帮助吗? :) 现在你看到那里发生了什么吗?
  • 很好的可视化,不是我不明白指针是如何重新排列的,我不明白 reverse_list 代码在做什么。你们俩都给出了很好的答案!非常感谢。
  • 在阅读 Pierres 答案时看到您的答案确实很有帮助。一旦我理解了它,我决定尝试迭代解决方案而不是递归,只是为了巩固事情。
【解决方案2】:
# 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方法

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方法

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 方法

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)具有您可能需要的所有功能和灵活性.

【讨论】:

  • 这不能回答问题,是吗?
  • @SergioTulentsev 你睡过吗?
  • @WandMaker:我正要:)
  • 你是对的,它没有。我没有正确理解这个问题
  • 是的,我明白了。我这样做只是因为我必须这样做,这是我正在学习的课程的一部分。他们甚至告诉我们它从未很少使用,但很重要,因为这是一个常见的面试问题。
【解决方案3】:

如果有人希望在没有递归的情况下执行此操作,这是一个简单的解决方案

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]

【讨论】:

    猜你喜欢
    • 2012-02-23
    • 2016-04-22
    • 2016-08-11
    • 1970-01-01
    • 1970-01-01
    • 2014-02-27
    • 1970-01-01
    相关资源
    最近更新 更多