Есть ли в Ruby контейнеры, такие как стеки, очереди, связанные списки, карты или наборы? - PullRequest
53 голосов
/ 15 февраля 2011

Я проверил несколько учебных пособий по Ruby онлайн, и они, похоже, использовали массив для всего. Итак, как я могу реализовать следующие структуры данных в Ruby?

  • Штабеля
  • Очередь
  • Связанные списки
  • Карты
  • Установка

Ответы [ 5 ]

86 голосов
/ 15 февраля 2011

(перенесено из комментария)

Ну, массив может быть стеком или очередью, ограничивая себя методами стека или очереди (push, pop, shift, unshift).Использование push / pop дает поведение LIFO (последний пришел первым вышел) (стек), а использование push / shift или unshift / pop дает поведение FIFO (очередь).

Карты - это хешей , а класс Set уже существует.

Вы можете реализовать связанный список, используя классы, но массивы будут давать поведение, подобное связанному списку, используя стандартные методы массива.

28 голосов
/ 13 сентября 2016

Я полагаю, что большинство из них описано в приведенных выше ответах, но просто для краткого изложения для лучшего объяснения:

Стек:

stack = []
stack << 2 # push 2 => stack = [2]
stack << 3 # push 3 => stack = [2, 3]
stack.pop  # pop => 3, stack = [2]

Очередь:

# we have a Queue class
queue = Queue.new
queue << 2 # push 2 => queue = [2]
queue << 3 # push 3 => queue = [2, 3] (just a representation, it will be an object though)
queue.pop # pop 2

Связанный список:

# A very simple representation
class Node
  attr_accessor :value, :next_node

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

class LinkedList

  def initialize(value)
    @head = Node.new(value)
  end

  def add(value)
    current = @head
    while !current.next_node.nil?
      current = current.next_node
    end
    current.next_node = Node.new(value)
  end
end

ll = LinkedList.new
ll.add(10)
ll.add(20)

Карты:

# Hash incase of ruby
a = {} (or a = Hash.new)
a['one'] = 1 # a = {"one"=>1}
a['two'] = 2 # a = {"one"=>1, "two"=>2}

Набор:

# we have a Set class
require 'set'
s = Set.new         # <Set: {}>
s.add(1)            # <Set: {1}>
s.add(2)            # <Set: {1, 2}>
s.add(1)            # <Set: {1, 2}>
s.instance_of?(Set) # true
8 голосов
/ 15 февраля 2011

Да, хотя явно не по названию. Класс Array может использоваться как стек, очередь или связанный список. Например, push и pop заставляют его вести себя как стек. Ruby's Map - это класс Hash. В Ruby также есть класс Set, хотя для его использования необходимо импортировать модуль (require 'set').

5 голосов
/ 04 августа 2015

Язык Ruby на самом деле имеет класс Queue , который можно использовать как .... ждать его ... Очередь;)

Это потокобезопасный и простой в использовании,

Остальные ответы @James велики и точны.

0 голосов
/ 13 мая 2017

Я хотел бы добавить реализацию Deque (которая является более общей в использовании линейных DS) в Ruby:

class Node
  attr_accessor :value, :next, :prev
  def initialize(value, next_node, prev_node)
    @value = value
    @next = next_node
    @prev = prev_node
  end
end


class Deque
  attr_accessor :start, :end
  def initialize
    @start = @end = nil
  end

  def push_back(val)
    if @start.nil?
      @start = @end = Node.new(val, nil, nil)
    else
      @end.next = Node.new(val, nil, @end)
      @end.next.prev = @end
      @end = @end.next
    end
  end

  def pop_back
    if @start == @end #only one node
      @start = @end = nil
    else
      @end = @end.prev
      @end.next = nil
    end
  end

  def push_front(val)
    @start.prev = Node.new(val, @start, nil)
    @start = @start.prev
  end

  def pop_front
    if @start == @end #only one node
      @start = @end = nil
    else
      @start = @start.next
      @start.prev.next = nil
      @start.prev = nil
    end
  end

  def empty?
    @start.nil? && @end.nil?
  end

  def front
    @start.value unless self.empty?
  end

  def back
    @end.value unless self.empty?
  end

  def print(node)
    arr = []
    while node
      arr << node.value
      node = node.next
    end
    p arr
  end
end


q = Deque.new
q.push_back(1)
q.push_back(2)
q.push_back(3)
q.push_back(4)
q.print(q.start)
q.push_front(0)
q.push_front(-1)
q.print(q.start)
q.pop_back()
q.pop_back()
q.print(q.start)
q.pop_front()
q.pop_front()
q.print(q.start)
p q.front
p q.back

Выход:

[1, 2, 3, 4]
[-1, 0, 1, 2, 3, 4]
[-1, 0, 1, 2]
[1, 2]
1
2
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...