карта против hash_map в C ++ - PullRequest
       27

карта против hash_map в C ++

110 голосов
/ 03 февраля 2010

У меня вопрос с hash_map и map в C ++. Я понимаю, что map в STL, но hash_map не является стандартом. Какая разница между ними?

Ответы [ 6 ]

129 голосов
/ 03 февраля 2010

Они реализованы очень по-разному.

hash_map (unordered_map в TR1 и Boost; используйте их вместо этого) использовать хэш-таблицу, в которой ключ хэшируется в слот таблицы, а значение сохраняется в списке, связанном с этим ключом.

map реализован в виде сбалансированного двоичного дерева поиска (обычно красное / черное дерево).

unordered_map должен дать немного лучшую производительность для доступа к известным элементам коллекции, но map будет иметь дополнительные полезные характеристики (например, он хранится в отсортированном порядке, что позволяет обход от начала до конца). unordered_map будет быстрее при вставке и удалении, чем map.

34 голосов
/ 03 февраля 2010

hash_map было распространенным расширением, предоставляемым многими реализациями библиотеки. Именно поэтому он был переименован в unordered_map, когда был добавлен в стандарт C ++ как часть TR1. Карта обычно реализуется с помощью сбалансированного бинарного дерева, такого как красно-чёрное дерево (реализации могут быть разными). hash_map и unordered_map обычно реализуются с помощью хеш-таблиц. Таким образом, порядок не поддерживается. unordered_map insert / delete / query будет O (1) (постоянное время), где map будет O (log n), где n - количество элементов в структуре данных. Так что unordered_map быстрее, и если вас не интересует порядок пунктов, предпочтительнее, чем map. Иногда вы хотите поддерживать порядок (заказанный ключом), и для этого map будет выбором.

14 голосов
/ 03 февраля 2010

Некоторые из ключевых отличий заключаются в требованиях к сложности.

  • A map требуется O(log(N)) время для операций вставки и поиска, поскольку оно реализовано как Красно-Черное дерево структура данных.

  • Для unordered_map требуется «среднее» время O(1) для вставок и находок, но разрешено иметь время наихудшего случая O(N). Это связано с тем, что он реализован с использованием структуры данных Hash Table .

Таким образом, обычно unordered_map будет быстрее, но в зависимости от ключей и хэш-функции, которую вы храните, может стать намного хуже.

4 голосов
/ 03 февраля 2010

Спецификация C ++ не говорит точно, какой алгоритм вы должны использовать для контейнеров STL. Однако он накладывает определенные ограничения на их производительность, что исключает использование хеш-таблиц для map и других ассоциативных контейнеров. (Они чаще всего реализуются с красными / черными деревьями.) Эти ограничения требуют лучшей производительности для этих контейнеров в худшем случае, чем могут предоставить хеш-таблицы.

Однако многие люди действительно хотят иметь хеш-таблицы, поэтому ассоциативные контейнеры STL на основе хешей уже давно стали распространенным расширением. Следовательно, они добавили unordered_map и такие к более поздним версиям стандарта C ++.

2 голосов
/ 01 июля 2018

map реализовано из balanced binary search tree (обычно rb_tree), поскольку все члены в balanced binary search tree отсортированы, как и карта;

hash_map реализовано из hashtable.Поскольку все члены в hashtable не отсортированы, поэтому члены в hash_map(unordered_map) не отсортированы.

hash_map не является стандартной библиотекой c ++, но теперь она переименована в unordered_map (можно подуматьона переименовывается) и становится стандартной библиотекой c ++, поскольку c ++ 11 см. этот вопрос Разница между hash_map и unordered_map? для более подробной информации.

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

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чья структура примерно такова:

enter image description here

В приведенном ниже коде я дам основную часть 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);
        };

};

На рисунке ниже показано, что у hash_map есть 53 сегмента, и при вставке некоторых значений это внутренняя структура.

enter image description here

На изображении ниже показано некоторое различие между картой и hash_map (unordered_map), изображение получено с Как выбрать между картой и unordered_map? :

enter image description here

0 голосов
/ 26 мая 2017

Я не знаю, что дает, но hash_map занимает более 20 секунд, чтобы очистить () целочисленные ключи без знака 150K и значения с плавающей запятой. Я просто бегу и читаю чужой код.

Вот как он включает hash_map.

#include "StdAfx.h"
#include <hash_map>

Я читал это здесь https://bytes.com/topic/c/answers/570079-perfomance-clear-vs-swap

говорит, что clear () - это порядок O (N). Для меня это очень странно, но так оно и есть.

...