Какова правильная структура данных для очереди, поддерживающей операции 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). Но если структура, о которой вы сказали, существует, будет решение для сортировки:
- Enque каждый элемент один за другим стоит O (n)
- удалить все Макс(или мин) элемента по одному издержки 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 могут быть в состоянии, если вы хорошо с этими языками.
удачи
редактировать: Я не объяснил отсортированных хэш-таблиц,поэтому добавил ссылку на другую, чтобы объяснить их.