linkedlist结构_了解Ruby中的LinkedList数据结构

linkedlist结构

如果您熟悉数据结构,则可能听说过LinkedList

在本文中,我们将从头开始创建一个LinkedList,并说明此数据结构如何工作以及它的用途。

让我们首先说明一个链表的概念。

简单来说,LinkedList是一种由数据集合组成的数据结构。

LinkedList中的值表示节点,每个节点包含一个指向下一个节点的指针。 在LinkedList中,每个节点的数据可以是任何数据。 我们称第一个节点为头,最后一个为尾。

此数据结构类似于数组,因为我们可以将两者都用于存储线性数据。 尽管它们之间存在一些差异,但让我们深入研究它。

首先,在LinkedList中,检索元素的Big O时间复杂度为0(n)。 原因是对于链表,我们无法像数组一样通过索引来检索元素。

我们需要从头开始遍历列表,直到找到要检索的元素。

此时,您可能会认为最好使用数组而不是LinkedList。 因为我们在使用数组访问元素时具有更好的运行时复杂性。

现在让我们谈谈删除和插入。

数组中的这些操作消耗大量时间。 另一方面,LinkedList中这些操作的执行速度很快。 同样,数组的大小固定,链接列表是动态的,可以扩展其大小。
最终,链表所需的内存空间少于数组。

现在,我们准备开始实施链接列表…

首先,我们将创建节点类,该类将帮助我们将新节点追加到“链接”列表中。

class Node
  attr_accessor :value , :next_node
 
  def initialize (value, next_node = nil )
    @value = value
    @next_node = next_node
  end
end

现在我们有了Node类,我们可以创建LinkedList类。

class LinkedList
  attr_accessor :tail , :head
  def initialize
    @head = nil
    @tail = nil
  end
end

对于我们的LinkedList类,我们还定义了两个访问器(tail,head)。 头部将是LinkedList中的第一个元素,而尾部将是最后一个元素。

我们还使用了构造函数方法来分配初始值。

这是创建LinkedList的基本设置,要测试它,我们可以创建LinkedList类的实例。

list = LinkedList . new
puts list

然后在控制台中运行我们的ruby文件并查看输出。

user@PC/desktop/Ruby: ~$ ruby linked_list.rb
#<LinkedList:0x00000000051ff9a0>

现在,我们可以创建第一个方法来向LinkedList添加新元素。 我们将从添加add_first方法开始。

def add_first (data)
  @head = Node.new(data, @head)
end

现在,通过这种方法,我们可以在LinkedList的开头添加元素。 由于我们将@head设置为新节点,因此我们将数据和@head传递为第二个参数。 结果是该元素将被插入列表的第一个位置。

现在创建一个新方法,将其追加到列表的末尾。

def add_last (data)
  node = Node.new(number)
  if !@head
    @head = node
    @tail = node
    return
  end
  last_node = get_last()
  last_node.next_node = node
  @tail = node
end

private

def get_last
  return if !@head
  node = @head
  until node.next_node. nil ?
    node = node.next_node
  end
  return node
end

在这种情况下,我们有两种方法。 一个有助于获取最后一个节点,该节点是私有的,另一个有助于将该节点添加到列表的末尾。 在第一种方法中,我们首先创建一个新节点并传递数据。

然后,我们检查@head是否为nil,如果是,则将@head和@tail设置为新节点并返回,以便执行停止。 如果@head不为nil,则通过调用get_last方法获得最后一个节点。 然后将next_node设置为新节点,最后,我们将该节点分配给@tail。

很好,现在我们可以将新元素添加到列表的末尾和前面。 但是,通过创建在特定位置附加元素的方法,我们甚至可以做得更好,让我们看看如何做到这一点。

def add_at (index, data)
 if !@head
   @head = Node.new(data)
   return
 end
 if index == 0
   add_first(data)
   return
 end
 
 previous = get_node(index — 1 ) || get_last()
 node = Node.new(data, previous.next_node)
 previous.next_node = node
end

private

def get_node (index)
  return if !@head
  return @head if index === 0
 
  node = @head
  counter = 0
  until node.next_node. nil ?
    node = node.next_node
    counter+= 1
    return node if counter === index
  end
end

同样,这里还有另一个私有方法,可以帮助我们在特定索引处获取节点。 在add_at方法中,我们获取索引和数据,以及 @head为零,我们将@head分配给新节点。 然后返回以停止执行。 如果 @head不是零,我们检查索引是否等于0,如果索引等于0,我们调用add_first方法并传递数据。 这样,我们就可以重用始终是一个好习惯的方法。

然后,如果索引不为0,则创建一个名为previous的变量,并将其分配给get_node或get_last方法的结果值。 如果其中一个返回nil,则前一个变量将采用另一个方法的值。 然后,我们创建一个新节点,并将数据和previous.next_node作为第二个参数传递。 最后,我们将previous.next_node分配给刚创建的节点。

现在我们基本上可以将元素添加到列表中的任何特定位置了。

我们将执行相同的操作以删除元素。 我们将使用三种方法remove_firstremove_lastremove_at

def remove_first
  return nil if !@head
  @head = @head.next_node
end

def remove_last
  return nil if !@head
  if !@head.next_node
    @head = nil
    return
  end
  
  prev = @head
  node = @head.next_node
  while node.next_node do
    node = node.next_node
    prev = prev.next_node
  end
  @tail = prev
  prev.next_node = nil
end

def remove_at (index)
  return if !@head
  if index == 0
    @head = @head.next_node 
    return
  end
  
  previous = get_node(index- 1 )
  if !previous || !previous.next_node
    return
  end
  previous.next_node = previous.next_node.next_node
end

这三种方法遵循与我们过去附加的逻辑相同的逻辑。 唯一的区别是操作(删除/添加)。

最后,我们要获取第一个元素,清除LinkedList并获取大小,让我们放置这些方法。

def clear
  @head = nil
  @tail = nil
end

def size
  return 0 if !@head
  node = @head
  counter = 0
  while node do
    node = node.next_node
    counter += 1
  end
  counter
end

def get_first
  @head.value
end

在clear方法中,我们只将@head和@tail分配给nil。 挺容易。 在get_first方法中,我们返回@head的值。 在size方法中,我们遍历头部并创建一个计数器,直到节点为nil,然后返回该计数器。 真的也很简单。

太棒了,我们已经用不同的方法实现了链表数据结构。

从那以后,LinkedList是一个很棒的数据结构,可以在计算机中实现。 也有队列和堆栈。 了解它的工作原理非常重要,因为许多应用程序都使用链表来存储数据,因为它们可以执行数组无法执行的恒定操作。

在此处查看LinkedList的不同用法。

在现实世界中,数据结构使用的内存空间可能会决定巨大的变化。 这就是为什么LinkedList在某些情况下如此有用的原因。 重要的是要知道在某些情况下使用数组更好,因此一切都取决于您的需求。

希望您喜欢并学到一些新东西,如果喜欢可以分享这篇文章,并感谢您的阅读。

翻译自: https://hackernoon.com/understanding-linkedlist-data-structure-in-ruby-4q653yqo

linkedlist结构

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值