ruby中没有扩展数组的最佳链表?

ruby中没有扩展数组的最佳链表?,ruby,data-structures,linked-list,singly-linked-list,Ruby,Data Structures,Linked List,Singly Linked List,在Ruby中实现链表而不使用/扩展Array类的最佳方法是什么?这是我过去使用过的一个实现,但它似乎不是最好的实现方式: class Node attr_accessor :value, :next_node def initialize(value = nil) @value = value end def to_s @value end end class SinglyLinkedList attr_

在Ruby中实现链表而不使用/扩展Array类的最佳方法是什么?这是我过去使用过的一个实现,但它似乎不是最好的实现方式:

class Node

    attr_accessor :value, :next_node

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

    def to_s
        @value
    end

end

class SinglyLinkedList

    attr_accessor :head

    def initialize(first_value=nil)
        @head = Node.new(first_value) if first_value
    end

    def add(value)
        #adds a new node to the list, amakes it the new head and links it to the former head
        new_node = Node.new(value)
        new_node.next_node = @head

        @head = new_node
    end

    def remove
        @head = @head.next_node
    end
end

我假设你是为了自学而实施的,否则就没有任何意义了。只需使用
Array
,这是ruby的列表实现

在我看来,您应该用C编写这些练习,因为实现链表的全部目的是更接近机器并更好地理解它的工作原理。C是完成这项任务的更好的工具,了解计算机是如何工作的

这就是经典链表在大学里的教学方法:
O(n)
插入,
O(n)
搜索,以及
O(n)
删除。之后,大多数书都会讨论它的改进

我写在我的头顶,并没有做任何测试,但这应该给你一个想法,并希望一个练习,以纠正任何错误,你发现的。(更新:@Nitesh发现了一个拼写错误,并修复了它。希望它现在有一些测试)


我最近遇到了一个有趣的链表实现(不幸的是不确定在哪里),其中
节点
类实现了插入和删除方法。下面是双链接列表的
节点
类,但同样的原则也适用于单链接列表

class Node
  protected
  attr_writer :prev, :next

  public
  attr_reader :value, :prev, :next

  def initialize(value)
    @value = value
  end

  def remove
    @prev.next = @next if @prev
    @next.prev = @prev if @next
    @next = @prev = nil
  end

  def insert_after(node)
    remove

    @next = node.next
    @next.prev = self if @next
    @prev = node
    node.next = self
  end
end
我觉得这个实现很有趣,因为我发现它非常通用。只需要一个
节点
就可以开始构建列表并对其进行操作

head = Node.new(1)

middle = Node.new(2)
middle.insert_after(head)

tail = Node.new(3)
tail.insert_after(middle)

middle.remove
在这个实现的基础上,您可以构建一个更高级的API,它非常容易理解。以下是
LinkedList
Deque
的更完整版本。列表本身子类化了
节点
,并链接到列表的开头和结尾

class ListNode < Node
  protected :remove # prevent incorrect access to Node methods

  def initialize
    @next = @prev = self
  end

  def head
    @next unless @next == self
  end

  def tail
    @prev unless @prev == self
  end

  def add_to_head(node)
    node.insert_after(self)
  end

  def add_to_tail(node)
    node.insert_after(self.prev)
  end

  def each(&block)
    return enum_for(:each) unless block_given?
    node = @next
    while node != self
      yield node
      node = node.next
    end
  end

  def to_a
    each.collect {|node| node.value }
  end
end
更好的是
each
方法,它允许我们使用任何函数来搜索和迭代节点:

list = ListNode.new
list.add_to_head(Node.new(1))
list.add_to_head(Node.new(2))
list.add_to_head(Node.new(3))
list.add_to_head(Node.new(4))

# list each value
list.each {|node| puts node.value }

# select all nodes with values greater than 2
list.each.select {|node| node.value > 2 }

# find the first node with a value of 4
list.each.find {|node| node.value == 4 }

你不喜欢它的什么地方?(除了不起作用)Sergio,我粘贴了错误版本的SLL类。现在应该可以了。我不喜欢的是,我没有一个好的遍历或“find_node”方法。关于如何从零开始高效地实现这一点,您有什么想法吗?在链表中查找总是
O(n)
。只是走数组,取决于你认为什么是“高效”。访问一个节点是O(N)。@screenmutt:那就是作弊,什么也没做。这两个世界都是最糟糕的。因为你假装它是一个链表,所以你得到的界面是有限的。因为它是一个数组,所以不会得到O(1)个插入。谢谢!我喜欢你在这方面的改进。我这样做确实是为了自学,也是为了在Ruby中创建一个小型的Ruby库,其中包含供个人使用和参考的额外数据结构。在add、remove方法中设置成员变量缺少“@”。本应编辑答案,但不希望编辑两个字符。
# create a new list
list = ListNode.new

# add some items to the head or tail
list.add_to_head(Node.new('Hello'))
list.add_to_tail(Node.new('World'))
list.to_a # => ["Hello", "World"]

# remove items from the head
list.head.remove
list.to_a # => ["World"]
list.head == list.tail # => true

# remove items from the tail
list.tail.remove
list.to_a # => []
list = ListNode.new
list.add_to_head(Node.new(1))
list.add_to_head(Node.new(2))
list.add_to_head(Node.new(3))
list.add_to_head(Node.new(4))

# list each value
list.each {|node| puts node.value }

# select all nodes with values greater than 2
list.each.select {|node| node.value > 2 }

# find the first node with a value of 4
list.each.find {|node| node.value == 4 }