Есть ли коллекции очереди и стека?

Если нам нужны коллекции FIFO или LIFO (в основном push, pop и front/back), что мы должны использовать в Rust? Что-то вроде std::queue или std::stack из С++.

Ответ 1

Прежде всего, Rust не предлагает (в стандартной библиотеке) любую библиотеку с гарантированной задержкой для добавления элементов: коллекции Rust обычно могут выделять память при добавлении новых элементов, а выделение памяти может занимать неограниченное количество времени в худшем случай.

При этом для каждого случая есть два претендента:

  • стек может быть реализован либо поверх Vec, либо LinkedList (обе функции pop_back и push_back)
  • очередь может быть реализована либо поверх VecDeque, либо LinkedList (обе функции pop_front и push_back)

Разница между Vec* и LinkedList заключается в том, что последняя упрощена: для каждого вызова push_back выполняется выделение памяти. С одной стороны, это здорово, потому что это означает, что стоимость push_back не зависит от количества элементов, уже находящихся в коллекции, с другой стороны... ну, распределение памяти может занять очень много времени.

Первое немного сложнее:

  • он имеет лучшую пропускную способность, благодаря более удобной кешировке
  • он имеет дополнительную емкость, гарантируя невыделение push_back, пока существует избыточная емкость.
  • он все еще сохраняет амортизацию O (1) push_back, даже если не резервировать избыточную мощность раньше времени

В общем, я бы посоветовал использовать Vec для стека и VecDeque для очереди.

Ответ 3

У Матье М. это почти идеально. Vec - ваш стек (LIFO), а VecDeque - двусторонняя очередь, которая поддерживает все 4 варианта (FIFO, FILO, LIFO и LILO), используя:

.push_front(x) | .front() | .pop_front()
.push_back(x)  | .back()  | .pop_back()

Если вы хотите максимально повысить свою эффективность, я рекомендую ознакомиться с разделом "Общие сведения о Rusts Vec и его способности создавать быстрые и эффективные программы". В нем более подробно рассказывается о том, как происходит распределение и перераспределение в Vec и VecDeque, но самый большой VecDeque заключается в том, что если вы можете предсказать максимальное количество элементов, которые вам понадобятся в очереди, вы можете использовать VecDeque::with_capacity(x) если вы знаете, когда инициализируете его, или .reserve_exact(x) если в какой-то момент вы точно знаете, сколько еще слотов вам понадобится

Я настоятельно рекомендую ознакомиться с документацией по Rust на std::collections, в ней есть превосходный список наиболее распространенных коллекций, используемых в Rust, а также предложения о том, когда выбирать каждую из них.

И последнее, VecDeque не является частью прелюдии по умолчанию в Rust, поэтому, если вы хотите использовать ее, вам нужно включить это:

use std::collections::VecDeque;