Как выбрать карту и unordered_map?

Предположим, я хотел отобразить данные со строкой в ​​качестве ключа. Какой контейнер следует выбрать, map или unordered_map? unordered_map занимает больше памяти, поэтому допустим, что память не является проблемой, и проблема в скорости.

unordered_map обычно должна давать среднюю сложность O (1) с наихудшим случаем O (n). В каких случаях он достигнет O (n)? Когда map получает больше времени, чем unordered_map? Это случается, когда n мало?

Предполагая, что я буду использовать STL unordered_map со значением по умолчанию haser Vs. карта. строка - это ключ.

Если я собираюсь итерации по элементам, а не доступа к отдельному элементу каждый раз, предпочитаю ли я map?

Ответ 1

На практике, если память не проблема, unordered_map всегда быстрее, если вы хотите получить один элемент.

Худший случай теоретический и связан с одним хешем, учитывающим все элементы. Это не имеет практического значения. unordered_map замедляется, как только у вас есть хотя бы log N элементов, принадлежащих к одному и тому же хэшу. Это также не имеет практического значения. В некоторых специальных сценариях вы можете использовать специальный алгоритм хэширования, который обеспечивает более равномерное распределение. Для обычных строк, которые не имеют определенного шаблона, общие хэш-функции, идущие с unordered_map, также хороши.

Если вы хотите отсортировать карту (используя итераторы) отсортированным способом, вы не можете использовать unordered_map. Наоборот, map не только позволяет это, но также может предоставить вам следующий элемент на карте, основанный на аппроксимации ключа (см. Методы lower_bound и upper_bound).

Ответ 2

                       | map              | unordered_map
---------------------------------------------------------
element ordering       | strict weak      | n/a 
                       |                  |
common implementation  | balanced tree    | hash table
                       | or red-black tree|  
                       |                  |
search time            | log(n)           | O(1) if there are no hash collisions
                       |                  | Up to O(n) if there are hash collisions 
                       |                  | O(n) when hash is the same for any key
                       |                  |     
Insertion time         | log(n)+rebalance | Same as search
                       |                  | 
Deletion time          | log(n)+rebalance | Same as search
                       |                  | 
needs comparators      | only operator <  | only operator ==
                       |                  |
needs hash function    | no               | yes
                       |                  |
common use case        | when good hash is| In most other cases. 
                       | not possible or  | 
                       | too slow. Or when|
                       | order is required| 

Ответ 3

В каком контейнере я должен выбрать, карту или unordered_map? unordered_map занимает больше памяти, поэтому пусть память не является проблемой, и проблема заключается в скорости.

Профиль, а затем решите. unordered_map, как правило, быстрее, но он меняется в каждом случае.

В каких случаях он мог бы добраться до O (n)?

Когда хеширование не является хорошим, и куча элементов присваивается тем же ячейкам.

Когда карта получает больше времени, чем unordered_map? Означает ли это, когда n мало?

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


Самое главное при принятии решения - требования к порядку и отсутствие аннулирования итератора. Если вам тоже нужно, вы должны использовать map. В противном случае unordered_map.

Ответ 4

В каких случаях он достигнет O (n)?

если у вас есть такая хеш-функция bad, которая создает одно и то же значение хэша для всех перемещений ввода (т.е. создает коллизии)...

В каком контейнере я должен выбрать, отобразить карту или unordered_map?

У вас всегда есть вопросы, касающиеся требований и вида/объема данных.

Когда карта получает больше времени, чем unordered_map?

Это просто разные структуры. Вам лучше сделать выбор, чтобы использовать один из них в зависимости от ваших типичных случаев использования (принимая во внимание, какие данные у вас есть и его количество)

Это hppaen, когда n мало?

В случае небольшого количества данных все зависит от конкретной реализации STL... Поэтому иногда даже простой вектор/массив может быть быстрее, чем ассоциативные контейнеры...