Освоение структур данных в Ruby — Очереди

Очереди — это особый вид связанные списки что позволяет вам обрабатывать коллекцию элементов переменного размера в порядке поступления (FIFO). Как и все структуры данных, которые мы видели до сих пор; очереди — это просто последовательности соединенных узлов.

Отличительной чертой очередей является то, что порядок поиска гарантированно будет первым пришел первым.

В отличие от того, что происходит с другими списками, которые мы видели; очереди не позволят нам вставлять/удалять элементы в случайных местах. Все элементы вставляются в начало очереди и удаляются из ее хвоста.

Вот как будет выглядеть очередь, содержащая два элемента:

[1 | next] -> [2 | next] -> X (nil)

Теперь предположим, что мы хотим сохранить новый элемент:

[1 | next] -> [2 | next] -> [3 | next] -> X (nil)

И теперь мы хотим удалить один:

[2 | next] -> [3 | next] -> X (nil)

Обратите внимание, как очереди растут к хвосту и сжимаются с головы.

Интерфейс очередей

По сравнению с другими список одинаковых структур данныхинтерфейс для очередей довольно прост, потому что с ними было мало операций.

Хотя вы можете добавить вспомогательные методы, такие как find_first или cat, я думаю, что эти методы затемняют семантику этой структуры данных, и поэтому я решил их не использовать.

Детали реализации

Каждый элемент в очереди представлен узлом, который содержит два атрибута:

  • Значение, которое содержит текущий узел.
  • Указатель на следующий узел в очереди.

Первый узел очереди называется головным, а последний — хвостовым. Чтобы отметить конец очереди, мы должны установить следующий указатель последнего элемента равным нулю.

Далее следует краткое описание каждого метода, его сложности и исходного кода.

Инициализировать

Этот метод является конструктором очереди. Он создает пустую очередь, устанавливает головной узел в nil и длину очереди в 0.

Сложность этого метода составляет O(1).

def initialize
  self.head = nil
  self.length = 0
end

поставить в очередь

Создает новый узел для вставки значения в очередь. Если в очереди нет узлов, новый узел становится головным; в противном случае он добавляется в конец очереди.

Поскольку очередь хранит указатели на свою голову и хвост, сложность этого метода составляет O(1).

def enqueue data
  node = Node.new data
  unless head
    self.head = node
  else
    self.tail.next = node
  end
  self.tail = node
  self.length += 1
end

Удалить из очереди

Удаляет элемент из очереди. В отличие от того, что происходит в обычных связанных списках, удаление в очередях происходит просто, потому что они всегда происходят в начале очереди.

Чтобы удалить элемент из очереди, мы указываем голову на узел, который находится рядом с ним, и присваиваем хвосту значение nil, если очередь содержит только один элемент.

def dequeue
  return nil unless self.length > 0
  self.head = self.head.next
  self.tail = nil if self.length == 1
  self.length -= 1
end

заглянуть

Возвращает узел, находящийся в начале очереди, не удаляя его, или nil, если очередь пуста.

Поскольку dequeue не возвращает удаляемый элемент, просмотр — это путь, если вам нужно что-то сделать с этим элементом.

Сложность этого метода составляет O(1).

def peek
  self.head
end

чистый

Удаляет все элементы из очереди.

def clear
  while self.peek
    dequeue
  end
end

Каждый

Этот метод проходит по очереди, выдавая по одному элементу за раз, пока не достигнет последнего элемента.

Из-за семантики очередей я не очень люблю такие методы, как этот, но должен признать, что время от времени они могут пригодиться. (т. е. во время выполнения сеансов отладки.)

Сложность получения следующего элемента в очереди составляет O (1). Сложность получения всей очереди составляет O(n).

def each
  return nil unless block_given?
  current = self.head
  while current
    yield current
    current = current.next
  end
end

Распечатать

Распечатайте содержимое очереди, пройдя ее элементы.

Сложность этого метода составляет O(n).

def print
  if self.length == 0
    puts "empty"
  else
    self.each { |node| puts node.data }
  end
end

Когда использовать очереди

Очереди хорошо работают в тех случаях, когда вам нужно обрабатывать элементы в порядке очереди.

Регистрация на конференции, системы онлайн-продаж и диспетчеры событий — все это хорошо подходит для очередей.

Как это происходит с другими структурами данных, которые мы видели до сих пор; очереди отлично работают для относительно небольшого набора данных переменного размера. Если вам нужно обрабатывать миллионы элементов, вам придется подождать, пока мы не перейдем к «продвинутым структурам данных» в этой серии.

Итак, это все об очередях. Я надеюсь, что вам понравилось!

В следующий раз, Стэкс. Следите за обновлениями!

PS: если вы являетесь участником программы Kindle Unlimited, вы можете прочитать немного отполированную версию этой серии бесплатно на вашем устройстве Kindle.


Структуры данных с нуля — Ruby Edition.

Похожие записи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *