返回Ruby中链表的头节点?

时间:2014-08-28 02:29:20

标签: ruby

我有以下链接列表实现:

class LinkedList
  def initialize
    @head = nil
  end

  def return_head
    previous_head = @head
    previous_head.next = nil # I want to return a clean node, without nexts
    @head = @head.next
    return previous_head
  end

  def add_element(value)
    if @head.nil?
      @head = Node.new(value)
    else
      new_node = Node.new(value)
      @head.next = new_node
    end
  end

end

class Node
  attr_accessor :data, :next
  def initialize(data)
    @data = data
  end
end

我的问题在于return_head方法。当我做previous_head.next = nil时,因为我想返回一个节点,头部本身,没有下一个。由于我将下一个设置为nil,然后当我执行@head = @head.next时,@headnil

我怎么解决这个问题?

3 个答案:

答案 0 :(得分:0)

def return_head
  previous_head = @head
  next_head = @head.next
  @head.next = nil # I want to return a clean node, without nexts
  @head = next_head
  return previous_head
end

答案 1 :(得分:0)

您的问题是,您将@headprevious_head视为不同的对象,但它们不是。

致电时

previous_head.next = nil # I want to return a clean node, without nexts

next的{​​{1}}属性(因此previous_head)设置为@head,因此当您尝试再次从nil访问它时已经@head

要解决此问题,您需要颠倒操作顺序,首先设置新的nil,然后从@head中删除next节点:

previous_head

另外,您可能还想查看@ Cary的答案,因为您的 def return_head previous_head = @head @head = @head.next previous_head.next = nil # I want to return a clean node, without nexts return previous_head end 方法实际上并没有添加元素,而是替换了第二个元素(您可以“#l; ll有一个零,一个或两个元素的列表 - 不再......)

答案 2 :(得分:0)

问题

add_elements有一个错误:@head在添加第一个元素后永远不会更改,只会更改@head.next

即使修复了add_elements,但如果没有干预return_head,则无法执行add_element两次。如果连续两次调用return head,你也可以实现一个简单的堆栈。

要连续执行return_head两次或更多次,您需要保存列表的第一个节点并使用node.next逐步浏览列表,直到找到倒数第二个节点。我已在单链接列表下完成此操作。

删除节点时,我选择返回node.data,而不是node,因为后者已从列表中删除,因此您只需提取data即可

您的另一个选择是实现双链表,我在下面也做了。

单链接列表

<强>代码

class SingleLinkedList
  attr_reader :head

  def initialize
    @head = nil
    @tail = nil
  end

  def delete_and_return_head
    data = @head.data
    delete_head
    data
  end

  def delete_head
    return if @head.nil?
    if @start == @head
      @start = nil
      @head = nil
    else
      @head = find_prev
      @head.next = nil
    end
  end

  def add_element(value)
    new_node = Node.new(value)
    if @head.nil?
      @start = new_node
    else
      @head.next = new_node
    end  
    @head = new_node
  end

private

  def find_prev
    node = @start
    node = node.next while node.next.next
    node
  end

end

class Node
  attr_accessor :data, :next
  def initialize(data)
    @data = data
  end
end

示例

创建链接列表

l = SingleLinkedList.new #=> #<SingleLinkedList:0x0000010200be70 @head=nil, @tail=nil>

添加元素

l.add_element(:dog)      #=> #<Node:0x0000010184cbf8 @data=:dog>
l.head                   #=> #<Node:0x0000010184cbf8 @data=:dog>
l.head.data              #=> :dog
l.head.next              #=> nil
dog = l.head             #=> #<Node:0x0000010184cbf8 @data=:dog>

l.add_element(:cat)      #=> #<Node:0x00000102207da0 @data=:cat>
l.head.data              #=> :cat
dog.next.data            #=> :cat
cat = l.head             #=> #<Node:0x00000102207da0 @data=:cat>

l.add_element(:pig)      #=> #<Node:0x000001021e4dc8 @data=:pig>
l.head.data              #=> :pig
cat.next.data            #=> :pig

删除并返回元素

l.delete_and_return_head #=> :pig
l.head.data              #=> :cat
l.head.next              #=> nil

l.delete_and_return_head #=> :cat
l.head.data              #=> :dog
l.head.next              #=> nil

双重链接列表

<强>代码

class DoubleLinkedList
  attr_reader :head

  def initialize
    @head = nil
  end

  def delete_and_return_head
    data = @head.data
    delete_head
    data
  end

  def delete_head
    return nil if @head.nil?
    if @head.prev.nil?
      @head = nil
    else
      @head.prev.next = nil
      @head = @head.prev
    end
  end  

  def add_element(value)
    new_node = Node.new(value)
    unless @head.nil?
      new_node.prev = @head
      @head.next = new_node
    end  
    @head = new_node
  end
end

class Node
  attr_accessor :data, :next, :prev
  def initialize(data)
    @data = data
  end
end

示例

创建链接列表

l = DoubleLinkedList.new #=> #<DoubleLinkedList:0x00000101048a60 @head=nil>

添加元素

l.add_element(:dog)      #=> #<Node:0x00000101039a60 @data=:dog>
l.head                   #=> #<Node:0x00000101039a60 @data=:dog>
l.head.data              #=> :dog
l.head.prev              #=> nil
l.head.next              #=> nil
dog = l.head             #=> #<Node:0x00000101039a60 @data=:dog>

l.add_element(:cat)      #=> #<Node:0x00000101874450 @data=:cat,
                         #    @prev=#<Node:0x00000101039a60 @data=:dog>>
l.head.data              #=> :cat
l.head.prev.data         #=> :dog
dog.next.data            #=> :cat
cat = l.head             #=> #<Node:0x00000101874450 @data=:cat,
                         #    @prev=#<Node:0x00000101039a60 @data=:dog>>

l.add_element(:pig)      #=> #<Node:0x00000101110fb0 @data=:pig,
                         #    @prev=#<Node:0x00000101874450 @data=:cat,
                         #    @next=#<Node:0x00000101110fb0 ...>,
                         #    @prev=#<Node:0x00000101039a60 @data=:dog>>>
l.head.data              #=> :pig
l.head.prev.data         #=> :cat
cat.next.data            #=> :pig

删除并返回元素

l.delete_and_return_head #=> :pig

l.head.data              #=> :cat
l.head.next              #=> nil
l.head.prev.data         #=> :dog
dog.next.data            #=> :cat

l.delete_and_return_head #=> :cat

l.head.data              #=> :dog
l.head.next              #=> nil
l.head.prev              #=> nil