Як вибрати між картою та unordered_map?


83

Припустимо, я хотів зіставити дані із рядком як ключем. Який контейнер я повинен був вибрати, mapабо unordered_map? unordered_mapзаймає більше пам’яті, тож припустимо, пам’ять не є проблемою, а проблема полягає в швидкості.

unordered_mapяк правило, повинні давати середню складність O (1) з найгіршим випадком O (n). У яких випадках воно потрапляло б до O (n)? Коли час mapотримує більше часу, ніж unordered_map? Чи трапляється це, коли n мало?

Припускаючи, що я б використовував STL unordered_mapіз типовим хасером Vs. карта. рядок - це ключ.

Якщо я збираюся робити ітерацію над елементами, а не отримувати доступ до окремого елемента щоразу, чи слід віддавати перевагу map?


3
Вам потрібно відсортувати елементи на відображенні?
Якийсь чувак-програміст

Яка реалізація unordered_mapвикористовує більше пам'яті?
Пітер Вуд,

Ви завжди маєте накладні витрати на пам’ять у хеш-карті, хоча вона, як правило, незначна.
ypnos

Це незначний момент, але коли ви згадуєте ітерацію, варто зазначити, що якщо ви виконуєте ітерацію під час вставки елементів, вам слід віддавати перевагу мапі над unordered_map.
Джон Макфарлейн,

Відповіді:


67

На практиці, якщо пам’ять не є проблемою, unordered_mapце завжди швидше, якщо ви хочете отримати доступ до одного елемента.

Найгірший випадок - теоретичний і пов’язаний з єдиним хешем, що враховує всі елементи. Це не має практичного значення. Він unordered_mapстає повільнішим, як тільки у вас є принаймні журнал N елементів, що належать одному хешу. Це також не має практичного значення. У деяких спеціальних сценаріях ви можете використовувати певний алгоритм хешування, який забезпечує більш рівномірний розподіл. Для звичайних рядків, які не мають певного шаблону, загальні хеш-функції, які unordered_mapпостачаються, є такими ж хорошими.

Якщо ви хочете пройти карту (за допомогою ітераторів) у сортуванні, ви не можете використовувати unordered_map. Навпаки, mapне тільки дозволяє це, але також може надати вам наступний елемент на карті на основі наближення ключа (див. lower_boundТа upper_boundметоди).


6
Ця відповідь в кращому випадку оманлива. Неправда, що "невпорядкована_карта завжди швидша для одноелементного доступу" - єдине, що я можу придумати, це завжди правда, це те, що вона завжди швидше амортизується та асимптотично . "Амортизований" є важливим застереженням на практиці: припускаючи, що він реалізований як якась хеш-таблиця, якщо я правильно пам'ятаю свої хеш-таблиці, коли ви вирощуєте її, вставляючи елементи, вона буде "гикати" операцією Ω (n) раз у раз. Це може чи не може сприймати будь-яка конкретна програма.
Don Hatch

209
                       | 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| 

6
Коментар щодо загальної реалізації: Червоно-чорне дерево - це своєрідне збалансоване дерево (або, більш конкретно, різновид самобалансуючого бінарного дерева пошуку).
HelloGoodbye

2
ребаланс зайняв би не більшеlog(n)
mtk

А як щодо ітерації всіх елементів?
Шашват,

7

У яких випадках воно потрапляло б до O (n)?

якщо у вас така погана хеш-функція, яка видає однакове хеш-значення для всіх вхідних штрингів (тобто викликає зіткнення) ...

Який контейнер я мав вибрати, карту чи unordered_map?

Це завжди питання вимог та виду / обсягу даних, якими ви володієте.

Коли карта отримує більш ефективний час, ніж unordered_map?

Це просто різні структури. Для використання одного з них вам краще задуматися, залежно від типових випадків використання (враховуючи, які у вас дані та їх обсяг)

Чи є hppaen, коли n мало?

У випадку невеликого обсягу даних все залежить від конкретної реалізації STL ... Тому іноді навіть звичайний вектор / масив може бути швидшим, ніж асоціативні контейнери ...


7

Який контейнер я мав вибрати, карту чи unordered_map? unordered_map займає більше пам'яті, тому припустимо, що пам'ять не є проблемою, а проблема полягає в швидкості.

Профілюйте, а потім вирішіть. unordered_mapяк правило, швидше, але це залежить від випадку.

У яких випадках воно потрапляло б до O (n)?

Коли хешування не є добрим, і до тих самих бункерів призначається купа елементів.

Коли карта отримує більш ефективний час, ніж unordered_map? Чи буває це, коли n мало?

Можливо, ні, але сформулюйте це, якщо вам дійсно все одно. Наявність контейнера невеликого розміру буде вузьким місцем вашої програми здається надзвичайно малоймовірним. У будь-якому випадку, простий vectorлінійний пошук може бути швидшим у таких випадках.


Найголовніше при прийнятті рішення - це вимоги впорядкування та відсутність анулювання ітератора. Якщо вам потрібно будь-яке, вам доведеться скористатися map. В іншому випадку unordered_map.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.