Ruby 递归与链表

Ruby 递归与链表,ruby,list,recursion,Ruby,List,Recursion,我想看看链表的表示形式。我创建了一个用于创建链接列表的类: class LinkedListNode attr_accessor :value, :next_node def initialize(value, next_node = nil) @value = value @next_node = next_node end def print_values(list_node) print "#{list_node.value} --> "

我想看看链表的表示形式。我创建了一个用于创建链接列表的类:

class LinkedListNode
  attr_accessor :value, :next_node

  def initialize(value, next_node = nil)
    @value = value
    @next_node = next_node
  end
  def print_values(list_node)
    print "#{list_node.value} --> "
    if list_node.next_node.nil?
      print "nil"
      return
    else
      print_values(list_node.next_node)
    end
  end

  node1 = LinkedListNode.new(37)
  node2 = LinkedListNode.new(99, node1)
  node3 = LinkedListNode.new(12, node2)
  print_values(node3)
end
我得到:

practice.rb:24:in `<class:LinkedListNode>': undefined method `print_values' for LinkedListNode:Class (NoMethodError)
practice.rb:24:in`':LinkedListNode:Class(NoMethodError)的未定义方法“print\u values”

递归是一种调用自身的方法吗?有可能让一个方法调用另一个方法来代替递归吗?或者不允许调用其他方法?

您应该将处理类的代码移出类定义:

class LinkedListNode

  attr_accessor :value, :next_node

  def initialize(value, next_node = nil)
    @value = value
    @next_node = next_node
  end

  def print_values(list_node)
    print "#{list_node.value} --> "
    if list_node.next_node.nil?
        print "nil"
        return
    else
        print_values(list_node.next_node)
    end
  end
end

node1 = LinkedListNode.new(37)
node2 = LinkedListNode.new(99, node1)
node3 = LinkedListNode.new(12, node2)

node3.print_values(node3)
该代码还存在许多其他问题,例如
print_values
被认为是类方法,而不是实例方法,但主要问题是上面提到的。以下是我如何将代码转换为使用类方法打印值:

class LinkedListNode

  attr_accessor :value, :next_node

  def initialize(value, next_node = nil)
    @value = value
    @next_node = next_node
  end 

  def self.print_values list_node
    print "#{list_node.value} --> "
    if list_node.next_node.nil?
        print "nil"
        return
    else
        print_values(list_node.next_node)
    end 
  end 
end

node1 = LinkedListNode.new(37)
node2 = LinkedListNode.new(99, node1)
node3 = LinkedListNode.new(12, node2)

LinkedListNode.print_values node3
希望能有帮助

NB由@joelparkerhenderson提供的答案实际上更好

递归是一种调用自身的方法吗

是的,一般来说。有关详细信息、示例和例外情况,请参阅

如果简化方法,您可能能够理解自己代码中的递归

您编写的代码更类似于过程代码,而Ruby通常使用更类似于以下内容的面向对象代码:

class LinkedListNode

  attr_accessor :value, :next_node

  def initialize(value, next_node = nil)
    @value = value
    @next_node = next_node
  end

  # This is how to write a typical Ruby recursive method.
  # Notice the method does something with this object's value,
  # then transfers control to the next object's same method name.

  def to_s
    "#{value} --> " + (next_node ? next_node.to_s : "nil")
  end

end

# This code is moved out of your class definition.
# This fixes one of the errors in your original code.

node1 = LinkedListNode.new(37)
node2 = LinkedListNode.new(99, node1)
node3 = LinkedListNode.new(12, node2)

print node3.to_s
是否可以对另一个方法进行方法调用以替换递归

是的,一般来说。例如,在代码中,可以调用使用迭代而不是递归的方法,类似于下面的示例

递归:

  def to_s
    "#{value} --> " + (next_node ? next_node.to_s : "nil")
  end
迭代:

  def to_s
    s = ""
    node = self
    while node != nil
      s += "#{value} --> " 
      node = next_node
    end
    s += "nil"
  end
使用迭代实现的算法通常比使用递归实现的类似算法运行得快得多


某些类型的递归(包括这里的代码)比其他类型的递归更有效。您的代码是可以高效使用的代码的一个很好的例子。

您的
print\u values
方法是一个实例方法,尽管它不使用其中的实例

我相信您打算将实例数据用于实现:

class LinkedListNode
  attr_accessor :value, :next_node

  def initialize(value, next_node = nil)
    @value = value
    @next_node = next_node
  end
  def print_values
    print "#{value} --> "
    if next_node.nil?
      print "nil"
      return
    else
      next_node.print_values
    end
  end
end

node1 = LinkedListNode.new(37)
node2 = LinkedListNode.new(99, node1)
node3 = LinkedListNode.new(12, node2)
node3.print_values
另一个选项是将该方法设置为静态方法,该方法不需要实例,如下所示:

class LinkedListNode
  attr_accessor :value, :next_node

  def initialize(value, next_node = nil)
    @value = value
    @next_node = next_node
  end
  def self.print_values(list_node)
    print "#{list_node.value} --> "
    if list_node.next_node.nil?
      print "nil"
      return
    else
      print_values(list_node.next_node)
    end
  end
end

  node1 = LinkedListNode.new(37)
  node2 = LinkedListNode.new(99, node1)
  node3 = LinkedListNode.new(12, node2)
  LinkedListNode.print_values(node3)

这两个选项都将被视为递归的,因为该方法调用自身。关于递归没有任何规则(允许调用另一个方法),但有一些事情需要注意,例如,如果没有良好的停止条件,您的方法可能会“爆炸”,出现堆栈溢出异常。

为什么代码像
node1=LinkedListNode.new(37)
类LinkedListNode的定义内部
?当我将打印值放在外部(node1、node2、node3)时,我得到了未定义的打印值方法。所以我想我应该把它放在要定义的类中。但是我仍然没有定义。谢谢你对使用递归和不使用递归的解释。这两个例子对TCO都有很大帮助。感谢您的修复!我想我试过用类定义之外的类。应该休息一下。让它成为类方法或非类方法有什么区别?实例方法在实例上被调用,而类方法在类上被调用。作为一个虚拟示例,
5.plus(3)
将是一个实例方法,知道它是在整数实例上调用的,而
integer.sum(5,3)
将是一个类方法。非常好的答案,谢谢。当你们提到静态方法时,是mudadosbwa在下面提到的类方法吗?谢谢