Як вибрати між картою та 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.