Yanıtlar:
Çok farklı şekillerde uygulanırlar.
hash_map
( unordered_map
TR1 ve Boost'ta; bunun yerine bunları kullanın), anahtarın tablodaki bir yuvaya karma hale getirildiği ve değerin bu anahtara bağlı bir listede saklandığı bir karma tablo kullanın.
map
dengeli bir ikili arama ağacı (genellikle kırmızı / siyah bir ağaç) olarak uygulanır.
An unordered_map
, koleksiyonun bilinen öğelerine erişmek için biraz daha iyi performans sağlamalıdır, ancak a map
ek yararlı özelliklere sahip olacaktır (örneğin, baştan sona geçişe izin veren sıralı sırayla depolanır). unordered_map
ekleme ve silme işlemlerinde a'dan daha hızlı olacaktır map
.
hash_map
birçok kütüphane uygulaması tarafından sağlanan yaygın bir uzantıdır. Bu yüzden unordered_map
TR1'in bir parçası olarak C ++ standardına eklendiği zaman olarak yeniden adlandırıldı . harita genellikle kırmızı-siyah ağaç gibi dengeli bir ikili ağaçla gerçekleştirilir (uygulamalar elbette değişiklik gösterir). hash_map
ve unordered_map
genellikle karma tablolarla uygulanır. Böylece düzen korunmaz. unordered_map
ekle / sil / sorgu O (1) (sabit zaman) olacaktır burada harita O (log n) olacaktır, burada n, veri yapısındaki öğelerin sayısıdır. Yani unordered_map
daha hızlı ve eğer ilginizi çekmiyorsa öğelerin sırasına göre tercih edilmelidir map
. Bazen düzeni korumak istersiniz (anahtara göre sıralanır) ve map
bunun için seçim olur.
Temel farklılıklardan bazıları karmaşıklık gereksinimlerindedir.
A map
, Kırmızı-Siyah Ağaç veri yapısı O(log(N))
olarak uygulandığı için, ekleme ve bulma işlemleri için zaman gerektirir .
Bir unordered_map
, O(1)
ekleme ve buluntular için 'ortalama' bir süre gerektirir , ancak en kötü durum süresine sahip olmasına izin verilir O(N)
. Bunun nedeni, Hash Table veri yapısı kullanılarak uygulanmasıdır .
Bu nedenle, genellikle unordered_map
daha hızlı olacaktır, ancak anahtarlara ve sakladığınız hash işlevine bağlı olarak çok daha kötü hale gelebilir.
C ++ belirtimi, STL kapsayıcıları için tam olarak hangi algoritmayı kullanmanız gerektiğini söylemez. Bununla birlikte, performanslarına bazı kısıtlamalar koyar, bu da karma tabloların map
ve diğer ilişkili kapların kullanımını dışlar . (Genellikle kırmızı / siyah ağaçlarda uygulanırlar.) Bu kısıtlamalar, bu kapsayıcılar için karma tabloların sağlayabileceğinden daha iyi en kötü durum performansı gerektirir.
Bununla birlikte, birçok insan gerçekten karma tablolar istemektedir, bu nedenle karma tabanlı STL ilişkisel kapsayıcılar yıllardır yaygın bir uzantı olmuştur. Sonuç olarak, unordered_map
C ++ standardının sonraki sürümlerine ve benzerlerini eklediler .
map
genellikle dengeli bir ağaç olduğunu düşündüm, operator<()
yer belirleme aracı olarak kullanılmasıydı .
map
balanced binary search tree
(genellikle a rb_tree
) ' dan gerçeklenir , çünkü içindeki tüm üye balanced binary search tree
sıralanır ve harita da öyle;
hash_map
içindeki hashtable
tüm hashtable
üyeler sıralanmadığından, içindeki üyeler hash_map(unordered_map)
sıralanmaz.
hash_map
bir c ++ standart kitaplık değil, ancak şimdi olarak yeniden adlandırıldı unordered_map
( yeniden adlandırıldığını düşünebilirsiniz) ve c ++ standart kitaplık haline geldi çünkü c ++ 11 bu soruyu görüyor Hash_map ve unordered_map arasındaki fark? daha fazla ayrıntı için.
Aşağıda, iki tip haritasının nasıl uygulandığına dair kaynak kodundan bazı temel arayüzler vereceğim.
Aşağıdaki kod, haritanın yalnızca bir sarmalayıcı olduğunu balanced binary search tree
, hemen hemen tüm işlevinin yalnızca balanced binary search tree
işlevi çağırdığını göstermek içindir .
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
yapısı biraz aşağıdaki gibi olanlardan uygulanır :
Aşağıdaki kodda ana kısmını vereceğim hashtable
ve sonra vereceğim 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
Tek üye gibi rb_tree
, hash_map's
tek üye de hashtable
. Aşağıdaki gibi ana kod:
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);
};
};
Aşağıdaki resim, hash_map'in 53 kovaya sahip olduğunu ve bazı değerleri eklediğini gösterir, dahili yapısı.
Aşağıdaki resim, map ve hash_map (unordered_map) arasındaki bazı farkları gösterir, resim, Harita ve unordered_map arasında nasıl seçim yapılır? :
Ne verir bilmiyorum ama hash_map'in 150K işaretsiz tamsayı anahtarlarını ve float değerlerini temizlemesi () 20 saniyeden fazla sürüyor. Sadece koşuyorum ve başka birinin kodunu okuyorum.
Hash_map'i bu şekilde içerir.
#include "StdAfx.h"
#include <hash_map>
Bunu burada okudum https://bytes.com/topic/c/answers/570079-perfomance-clear-vs-swap
clear (), O (N) 'nin sırasıdır. Bu benim için çok tuhaf, ama bu böyle.