std :: map с эффективным доступом к n-ному элементу - PullRequest
21 голосов
/ 14 января 2011

У меня есть набор данных, которые мне нужно сохранить на упорядоченной карте (т. Е. С помощью эффективной вставки, удаления и поиска элементов по ключу), но мне также нужно иметь возможность найти nth *Элемент 1002 *, не проходя всю карту (иногда на ней могут быть десятки тысяч элементов).

Я знаю один способ сделать это: использовать красное / черное дерево, но сохранить общее количестводочерних элементов на одной из ног каждого узла, а также.Это делает вставку и удаление немного медленнее (потому что вы должны обновить счетчики на каждом узле вдоль пути, как вы делаете), но вы можете найти элемент nth для любого n вПримерно в то же время, что и при поиске ключа.

Мне интересно, существует ли в C ++ реализация такой вещи, которую я могу использовать.Я мог бы написать это сам, если нет, но я бы действительно не хотел.


РЕДАКТИРОВАТЬ: я получил некоторые разъяснения по варианту использования для этого.Я немного неправильно понял: после поиска элемента по ключу им нужна возможность эффективно выяснить, по какому индексу найден элемент, чтобы правильно отобразить полосы прокрутки.

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

Ответы [ 7 ]

4 голосов
/ 14 января 2011

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

4 голосов
/ 13 июня 2012

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

контейнер ассоциативного / произвольного доступа

Полагаю, это может относиться и к вашему вопросу.


Я давно искал такую ​​структуру данных.

Недавно я нашел довольно многообещающую библиотеку, которая обладает всеми функциями, которые вы ищете.

См. Cntree :: set с произвольным доступом в O (log n).

вот ссылка. http://dl.dropbox.com/u/8437476/works/countertree/index.html

Хотя он, кажется, находится в стадии разработки, я вижу, что он вполне пригоден для использования.

2 голосов
/ 14 января 2011

Я никогда не использовал boost::multi_index_container<>, но похоже, что он может делать то, что вы хотите (хотя я не совсем уверен - это довольно сложная библиотека на первый взгляд).

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

Эта дополнительная гибкость достигается ценой: вставки и удаления в позициях, отличных от конца индекса, имеютлинейная сложность, тогда как эти операции имеют постоянное время для последовательных индексов.Эта ситуация напоминает различия в поведении сложности между std :: list и std :: vector: однако в случае индексов произвольного доступа при вставках и удалениях никогда не происходит копирования элементов, поэтому фактическое выполнение этих операций может быть приемлемымНесмотря на теоретический недостаток в отношении последовательных индексов.

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

0 голосов
/ 13 мая 2011

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

0 голосов
/ 14 января 2011

MS VC STL карта на фоне красного черного дерева.

Я не думаю, что возможно иметь эффективный поиск (по ключу) и эффективный произвольный доступ в одной и той же структуре данных.

Если эффективный произвольный доступ действительно важен, лучше хранить данные в векторном контейнере произвольного доступа. Упорядочение и поиск ключей могут быть выполнены с помощью дополнительных индексов. СУБД делают так.

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

0 голосов
/ 14 января 2011

Один из вариантов - разработка контейнера на основе std :: vector, но также с интерфейсом карты.Он будет хранить отдельное хеш-таблицу или двоичное дерево, которое использует ключи элементов для доступа к ним, но фактические значения будут указателями на внутренний массив, используемый вектором.склонны к тому или иному запаху дизайна у некоторых людей, но такая структура данных имеет свое место.Я видел, как это используется в коде для аппаратных драйверов в розничных системах, где два пользователя контейнера должны иметь к нему разные способы доступа.Когда используется «потому что он есть», это плохо, но спасает спасение при правильном использовании.

0 голосов
/ 14 января 2011

Попробуйте использовать упорядоченный список std :: list и используйте для поиска std :: binary_search.Упорядоченный список может быть реализован с использованием std :: list, а вставка узлов - с использованием std :: lower_bound.Есть много примеров этого в Интернете и на SO.

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