Когда вам нужен заказ, используйте заказанный контейнер. В дальнейшем нет смысла оплачивать стоимость сортировки.
Ваше текущее решение:
- Вставка
O(1)
- Извлечение
O(N log N)
- Удаление
O(N)
(это так же хорошо, как вы можете получить без сохранения там другого индекса)
Просто используя std::multi_map
вы можете получить:
- Вставка
O(log N)
- Извлечение
O(log N)
<- намного лучше, не так ли? Нам нужно найти конец диапазона </li>
- Снятие
O(N)
Теперь вы могли бы сделать немного лучше с std::map< key, std::vector<value> >
:
- Вставка
O(log M)
, где M
- количество отдельных клавиш
- Извлечение
O(1)
(begin
гарантированно амортизируется постоянным временем)
- Снятие
O(N)
Вы не можете толкнуть случайное удаление ... если только вы не захотите сохранить там другой индекс. Например:
typedef std::vector<value_type> data_value_t;
typedef std::map<key_type, data_value_t> data_t;
typedef std::pair<data_t::iterator,size_t> index_value_t;
// where iterator gives you the right vector and size_t is an index in it
typedef std::unordered_map<value_type, index_value_t> index_t;
Но поддержание этого второго индекса в актуальном состоянии подвержено ошибкам ... и будет сделано за счет других операций! Например, с этой структурой у вас будет:
- Вставка
O(log M)
-> сложность вставки в хэш-карту составляет O(1)
- Retrieval
O(N/M)
-> необходимо проиндексировать все значения в векторе, в среднем N/M
- Удаление
O(N/M)
-> поиск в хэш-карте O(1)
, разыменование O(1)
, удаление из вектора O(N/M)
, потому что нам нужно сместить примерно половину содержимого вектора. Использование list
даст O(1)
... но может быть не быстрее (зависит от количества элементов из-за компромисса памяти).
Также имейте в виду, что сложность хэш-карты является амортизированной. Запустите перераспределение, потому что вы переросли коэффициент загрузки, и эта конкретная вставка займет очень много времени.
Я бы действительно пошел с std::map<key_type, std::vector<value_type> >
вместо вас. Это лучший удар для доллара.