Какова правильная структура данных для очереди, поддерживающей операции Min, Max за время O(1)?

какова правильная структура данных для очереди, которая поддерживает операции Enque, Dequeue, Peak, Min и Max и выполняет все эти операции за O(1) Время.

наиболее очевидной структурой данных является связанный список, но Min, Max операции будут O (n). Приоритетная очередь-еще один идеальный выбор, но Enqueue, Dequeue должен работать в обычном режиме очереди. (ФИФО)

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

любая помощь очень ценится.

4 ответов


структура данных, которую вы ищете, не может быть разработана, если min() и max () фактически изменяют структуру. Если min () и max () похожи на peek () и предоставляют доступ только для чтения, то вы должны выполнить шаги в этот вопрос, добавив еще один deque, аналогичный тому, который используется для операций min() для использования в операции max (). Остальная часть этого ответа предполагает, что min() и max () На самом деле удалить соответствующие элементы.

С вам требуется enqueue () и dequeue (), элементы должны быть добавлены и удалены по порядку прибытия (FIFO). Простая двойная очередь (связанная или использующая круговой вектор) обеспечит это в O(1).

но добавляемые элементы могут изменить текущие значения min () и max (); однако при удалении старые значения min() и max () должны быть восстановлены... если только их не уберут на время. Это ограничение заставляет вас каким-то образом сортировать элементы. Любая Сортировочная структура (min-heap, max-куча, сбалансированное двоичное дерево,...) потребуется по крайней мере O (log n), чтобы найти позицию нового прибытия.

лучше всего соединить сбалансированное двоичное дерево (для min () и max ()) с двусвязным списком. Узлы дерева будут хранить набор указателей на узлы списка, отсортированных по любому ключу, который вы используете в min () и max (). В Java:

// N your node class; can return K, comparable, used for min() and max() 
LinkedList<N> list;           // sorted by arrival
TreeMap<K,HashMap<N>> tree;   // sorted by K
  • on enque (), вы бы добавили новый узел в конец list и добавить, что тот же узел, по его ключу, к HashMap в узле tree. O (log n).
  • on dequeue (), вы удалили бы узел с начала list, и из его HashMap в его узле в дереве. O (log n).
  • on мин (), вы будете искать 1-й элемент в дереве. O (1). Если вам нужно удалить его, у вас есть указатель на связанный список, поэтому O (1) на этой стороне; но O (log n) для восстановления баланса дерево, если это был последний элемент с конкретными К.
  • on Макс (), применяется та же логика; за исключением того, что вы будете искать последний элемент в дереве. Так что O (log n).
  • on ку (), глядя На, но не извлекая 1-й элемент в очереди, будет O (1).

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

на практике, разница между O (log n) и O (1) настолько низок, что реализация карты по умолчанию в STL c++O (log n) - based (дерево вместо хэша).


любая структура данных, которая может получить Min или Max в O(1) время нужно потратить хотя бы O (log n) на каждого Insert и Remove для поддержания элементов в частично отсортированном порядке. Структуры данных, которые достигают этого, называются в свою очередь.

основная очередь приоритетов поддерживает Insert, Max и RemoveMax. Существует несколько способов их создания, но двоичные кучи работы лучший.

все Insert, Min, RemoveMin, Max и RemoveMax С одной приоритетной очередью сложнее. Способ сделать это с помощью одной структуры данных, адаптированной из двоичной кучи, описан в статье:

Atkinson, Michael D., et al. "Min-max кучи и обобщенные очереди приоритетов." сообщения АСМ 29.10 (1986): 996-1000.

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


этой структуры не существует!

существует простой способ утвердить этот вывод.

Как мы все знаем,сложность проблемы сортировки O (nlogn). Но если структура, о которой вы сказали, существует, будет решение для сортировки:

  1. Enque каждый элемент один за другим стоит O (n)
  2. удалить все Макс(или мин) элемента по одному издержки O (n)

Что означает задача сортировки может быть решена с помощью O (n).Но это невозможно.


предположения:

Что вы заботитесь только о производительности, а не о пространстве / памяти / ...

решение:

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

вы можете сделать очередь и хэш-таблицу бок о бок.

пример:

допустим заказ 5 4 7 1 8 3

очередь - > 547813

хэш столе -> 134578

Enqueue:

1) Возьмите свой объект и вставьте в хэш-таблицу в правом ведре Min / Max всегда будет первым и последним индексом. (см. раздел сортированные хэш-таблицы)

2) Затем вставьте в свою очередь, как обычно.

3) можно / нужно связать две. Одной из идей было бы использовать значение хэш-таблицы в качестве указателя на очередь.

обе операции с большой хэш-таблице будет O (1)

Dequeue:

1) поп элемент кулака O (1)

2) удалить элемент из хэш-таблицы O (1)

Min / Max:

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

для лучшего объяснения отсортированных хэш-таблиц, https://stackoverflow.com/questions/2007212

Примечание: Я хотел бы отметить, что нет "нормальной" структуры данных, которая будет делать то, что вам требуется, о чем я знаю. Однако это не означает, что это невозможно. Если вы намерены попытаться реализовать структуру данных, скорее всего, вам придется сделать это для ваших потребностей и не сможете использовать текущие библиотеки. Возможно, вам придется использовать язык очень низкого уровня, например сборка для достижения этого, но, возможно, C или Java могут быть в состоянии, если вы хорошо с этими языками.

удачи

редактировать: Я не объяснил отсортированных хэш-таблиц,поэтому добавил ссылку на другую, чтобы объяснить их.