Лучшая структура данных для двухсортированного списка - PullRequest
3 голосов
/ 15 мая 2010

Мне нужна структура данных коллекции, которая может делать следующее:

  • сортируется
  • Позвольте мне быстро вытолкнуть значения из передней и задней части списка O (log n)
  • Остается отсортированным после ввода нового значения
  • Разрешить пользовательскую функцию сравнения, так как я буду хранить кортежи и хочу отсортировать по определенному значению
  • Безопасность потока не требуется
  • При желании разрешить эффективные поиски haskey () (я рад, что для этого мне нужна отдельная хеш-таблица)

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

Поскольку я заинтересован в производительности для умеренного количества элементов (я бы оценил менее 200 000), я не уверен в том, какая асимптотическая производительность мне требуется для этих операций. n не будет расти бесконечно, поэтому низкая постоянная производительность k в k * O(n) может быть столь же важной O(n). Тем не менее, я бы предпочел, чтобы операции вставки и pop занимали O(log n) времени.

Кроме того, есть ли какие-то конкретные реализации в Python? Я действительно хотел бы избежать написания этого кода самостоятельно.

Ответы [ 7 ]

2 голосов
/ 15 мая 2010

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

1 голос
/ 15 мая 2010

Если вы действительно можете разрешить O (log n) для pop, dequeue и insert, тогда вполне достаточно простого сбалансированного дерева поиска, такого как красно-черное дерево.

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

Существует также то, что называется min-max heap (см. Запись Binary Heap в Википедии), которая реализует в точности «двустороннюю приоритетную очередь», то есть очередь, в которую можно извлекать как с внешнего, так и с заднего конца. Однако там вы не можете получить доступ ко всему списку объектов по порядку, тогда как дерево поиска может быть эффективно итерировано в течение O (n) времени.

Преимущество кучи min-max состоит в том, что объекты current min и max могут быть прочитаны за O (1) время, а для поиска по дереву требуется O (log (n)) только для чтения объект min или max, если у вас нет кэшированных указателей, как я упоминал выше.

1 голос
/ 15 мая 2010

За исключением хеширования, вы ищете двустороннюю приоритетную очередь, или приоритетную деку.

Если ваша потребность в сортировке не ограничивается управлением минимальными и максимальнымиданные, другой структурой, на которую вы можете обратить внимание, может быть интервальная куча, которая имеет преимущество поиска O (1) как min, так и max, если вам нужно посмотреть значения (хотя deleteMin и deleteMax по-прежнему O (log (N)))).К сожалению, я не знаю каких-либо реализаций в Python, поэтому я думаю, что вам придется свернуть свой собственный.

Вот дополнение к учебнику алгоритмов, в котором описаны интервальные кучи, если вам интересно:

http://www.mhhe.com/engcs/compsci/sahni/enrich/c9/interval.pdf

1 голос
/ 15 мая 2010

Я полагаю, вам нужно отсортировать, потому что вы получаете доступ к элементу по рангу в отсортированном порядке?

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

С этой структурой, учитывая ранг элемента (даже мин / макс), вы можете получить доступ / удалить его за O (log n) времени.

Это делает все операции (доступ / вставка / удаление по рангу, всплывающее окно вперед / назад, вставка / удаление / поиск по значению) O (logn) время, в то же время позволяя настраивать методы сортировки.

Кроме того, очевидно, что в python есть реализация дерева AVL (одна из первых сбалансированных древовидных структур), которая поддерживает статистику заказов: http://www.python.org/ftp/python/contrib-09-Dec-1999/DataStructures/avl.README

Так что вам не понадобится пользовательская реализация.

1 голос
/ 15 мая 2010

Похоже на Пропустить список будет соответствовать всем вашим требованиям. В основном это отсортированный по динамическому размеру связанный список с O (log n) вставками и удалениями.

Я действительно не знаю Python, но эта ссылка, похоже, актуальна:

http://infohost.nmt.edu/tcc/help/lang/python/examples/pyskip/

1 голос
/ 15 мая 2010

Я предлагаю какое-то сбалансированное бинарное дерево, такое как красно-черное дерево.

A поиск в PyPi вызывает несколько реализаций. Поиск в Google даст вам больше.

bintrees в PyPi выглядит очень полным и имеет реализации как на Python, так и на C / Cython. Я не использовал его, поэтому будьте бдительны.

Красно-черное дерево сохраняется отсортированным, и большинство операций (вставка, удаление, поиск) - это O (log2 (N)), поэтому поиск элемента в дереве из 200 000 записей займет в среднем 17-18 сравнений. 1011 *

0 голосов
/ 15 мая 2010

Если бы это была Java, я бы использовал TreeSet с интерфейсом NavigableSet.

Это реализовано как красно-черное дерево.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...