Відповіді:
Вони реалізуються дуже різними способами.
hash_map
( unordered_map
у TR1 та Boost; використовуйте замість них) використовуйте хеш-таблицю, де ключ хешируется до слота в таблиці, а значення зберігається у списку, прив'язаному до цього ключа.
map
реалізується як збалансоване дерево бінарного пошуку (зазвичай це червоне / чорне дерево).
Аналіз unordered_map
повинен давати трохи кращі показники доступу до відомих елементів колекції, але map
додаток матиме додаткові корисні характеристики (наприклад, він зберігається у відсортованому порядку, що дозволяє пройти від початку до кінця). unordered_map
буде швидше вставляти та видаляти, ніж a map
.
hash_map
було поширеним розширенням, яке надали багато реалізацій бібліотеки. Саме тому він був перейменований, unordered_map
коли він був доданий до стандарту C ++ у складі TR1. карта, як правило, реалізована з врівноваженим бінарним деревом, як червоно-чорне дерево (реалізації залежать від курсу). hash_map
і unordered_map
зазвичай реалізуються за допомогою хеш-таблиць. Таким чином порядок не підтримується. unordered_map
Вставити / видалити / запит буде O (1) (постійний час), де на карті буде O (log n), де n - кількість елементів у структурі даних. Так unordered_map
швидше, і якщо ви не дбаєте про порядок предметів, слід віддавати перевагу над map
. Іноді хочеться підтримувати порядок (упорядкований ключем), і для цього map
був би вибір.
Деякі з ключових відмінностей полягають у вимогах щодо складності.
A map
потрібен O(log(N))
час для вставки та пошуку операцій, оскільки він реалізований як структура даних Red-Black Tree .
Потрібен unordered_map
"середній" час O(1)
для вставок та знахідок, але це може бути найгіршим часом O(N)
. Це тому, що він реалізований за допомогою структури даних Hash Table .
Так, як правило, unordered_map
буде швидше, але залежно від клавіш і хеш-функції, яку ви зберігаєте, може стати набагато гірше.
Специфікація C ++ не говорить точно, який алгоритм потрібно використовувати для контейнерів STL. Однак це ставить певні обмеження щодо їх продуктивності, що виключає використання хеш-таблиць для map
інших та асоціативних контейнерів. (Вони найчастіше реалізуються з червоними / чорними деревами.) Ці обмеження потребують кращої продуктивності для цих контейнерів, ніж їх можуть доставити хеш-таблиці.
Однак багато людей дійсно хочуть хеш-таблиць, тому контейнери-асоціативні контейнери на основі хешу вже багато років є поширеним розширенням. Отже, вони додавали unordered_map
та інше до пізніших версій стандарту C ++.
map
як правило, врівноважена btree через те, що вона використовує operator<()
як засіб визначення місця розташування.
map
реалізується з balanced binary search tree
(як правило, a rb_tree
), оскільки всі учасники в balanced binary search tree
сортуються, так це карта;
hash_map
реалізовано від hashtable
. Тому що всі члени в hashtable
несортовані, тому члени в hash_map(unordered_map)
не сортуються.
hash_map
не є стандартною бібліотекою c ++, але тепер вона перейменована на unordered_map
(можна подумати про її перейменоване) і стає c ++ стандартною бібліотекою, оскільки c ++ 11 див. це питання. Різниця між hash_map та unororder_map? для більш детальної інформації.
Нижче я наведу основний інтерфейс із вихідного коду того, як реалізується карта двох типів.
Нижче наведений код лише для того, щоб показати, що карта - лише обгортка balanced binary search tree
, майже вся його функція - це лише виклик balanced binary search tree
функції.
template <typename Key, typename Value, class Compare = std::less<Key>>
class map{
// used for rb_tree to sort
typedef Key key_type;
// rb_tree node value
typedef std::pair<key_type, value_type> value_type;
typedef Compare key_compare;
// as to map, Key is used for sort, Value used for store value
typedef rb_tree<key_type, value_type, key_compare> rep_type;
// the only member value of map (it's rb_tree)
rep_type t;
};
// one construct function
template<typename InputIterator>
map(InputIterator first, InputIterator last):t(Compare()){
// use rb_tree to insert value(just insert unique value)
t.insert_unique(first, last);
}
// insert function, just use tb_tree insert_unique function
//and only insert unique value
//rb_tree insertion time is : log(n)+rebalance
// so map's insertion time is also : log(n)+rebalance
typedef typename rep_type::const_iterator iterator;
std::pair<iterator, bool> insert(const value_type& v){
return t.insert_unique(v);
};
hash_map
:hash_map
реалізується з hashtable
структури якої приблизно так:
У наведеному нижче коді я дам основну частину hashtable
, а потім дає hash_map
.
// used for node list
template<typename T>
struct __hashtable_node{
T val;
__hashtable_node* next;
};
template<typename Key, typename Value, typename HashFun>
class hashtable{
public:
typedef size_t size_type;
typedef HashFun hasher;
typedef Value value_type;
typedef Key key_type;
public:
typedef __hashtable_node<value_type> node;
// member data is buckets array(node* array)
std::vector<node*> buckets;
size_type num_elements;
public:
// insert only unique value
std::pair<iterator, bool> insert_unique(const value_type& obj);
};
Як map's
тільки член є rb_tree
, hash_map's
єдиний член є hashtable
. Це основний код, як показано нижче:
template<typename Key, typename Value, class HashFun = std::hash<Key>>
class hash_map{
private:
typedef hashtable<Key, Value, HashFun> ht;
// member data is hash_table
ht rep;
public:
// 100 buckets by default
// it may not be 100(in this just for simplify)
hash_map():rep(100){};
// like the above map's insert function just invoke rb_tree unique function
// hash_map, insert function just invoke hashtable's unique insert function
std::pair<iterator, bool> insert(const Value& v){
return t.insert_unique(v);
};
};
Нижче на зображенні показано, коли у хеш-мапі є 53 відра, а вставити деякі значення - це внутрішня структура.
На зображенні нижче показано деяку різницю між картою та hash_map (unordered_map), зображення походить із способу вибору між картою та unordered_map? :
Я не знаю, що дає, але для очищення () 150K непідписаних цілих чисел та плаваючих значень потрібно hash_map більше 20 секунд. Я просто біжу і читаю чужий код.
Це, як вона включає hash_map.
#include "StdAfx.h"
#include <hash_map>
Я читав це тут https://bytes.com/topic/c/answers/570079-perfomance-clear-vs-swap
кажучи, що clear () є порядком O (N). Це для мене дуже дивно, але так воно і є.