Jawaban:
Mereka diterapkan dengan cara yang sangat berbeda.
hash_map
( unordered_map
di TR1 dan Boost; gunakan itu sebagai gantinya) gunakan tabel hash di mana kuncinya di-hash ke slot di tabel dan nilainya disimpan dalam daftar yang terkait dengan kunci itu.
map
diimplementasikan sebagai pohon pencarian biner yang seimbang (biasanya pohon merah / hitam).
An unordered_map
harus memberikan kinerja yang sedikit lebih baik untuk mengakses elemen koleksi yang diketahui, tetapi a map
akan memiliki karakteristik tambahan yang berguna (misalnya disimpan dalam urutan yang diurutkan, yang memungkinkan traversal dari awal hingga akhir). unordered_map
akan lebih cepat saat memasukkan dan menghapus daripada a map
.
hash_map
adalah ekstensi umum yang disediakan oleh banyak implementasi perpustakaan. Itulah mengapa itu diganti namanya unordered_map
ketika ditambahkan ke standar C ++ sebagai bagian dari TR1. map umumnya diimplementasikan dengan pohon biner yang seimbang seperti pohon merah-hitam (implementasinya bervariasi tentunya). hash_map
dan unordered_map
umumnya diimplementasikan dengan tabel hash. Dengan demikian ketertiban tidak terjaga. unordered_map
masukkan / hapus / kueri akan menjadi O (1) (waktu konstan) di mana peta akan menjadi O (log n) di mana n adalah jumlah item dalam struktur data. Jadi unordered_map
lebih cepat, dan jika Anda tidak peduli dengan urutan item harus lebih disukai map
. Terkadang Anda ingin menjaga ketertiban (dipesan oleh kunci) dan untuk itu map
akan menjadi pilihan.
Beberapa perbedaan utama terletak pada persyaratan kompleksitas.
A map
membutuhkan O(log(N))
waktu untuk operasi penyisipan dan pencarian, karena ini diimplementasikan sebagai struktur data Pohon Merah-Hitam .
An unordered_map
memerlukan waktu 'rata-rata' O(1)
untuk penyisipan dan penemuan, tetapi diizinkan untuk memiliki waktu kasus terburuk O(N)
. Ini karena diimplementasikan menggunakan struktur data Tabel Hash .
Jadi, biasanya, unordered_map
akan lebih cepat, tetapi tergantung pada tombol dan fungsi hash yang Anda simpan, bisa menjadi jauh lebih buruk.
Spesifikasi C ++ tidak mengatakan dengan tepat algoritme apa yang harus Anda gunakan untuk penampung STL. Namun, hal itu menempatkan batasan tertentu pada kinerja mereka, yang mengesampingkan penggunaan tabel hash untuk map
dan wadah asosiatif lainnya. (Mereka paling sering diterapkan dengan pohon merah / hitam.) Batasan ini memerlukan kinerja kasus terburuk yang lebih baik untuk penampung ini daripada yang dapat diberikan tabel hash.
Banyak orang benar-benar menginginkan tabel hash, bagaimanapun, jadi wadah asosiatif STL berbasis hash telah menjadi ekstensi umum selama bertahun-tahun. Akibatnya, mereka menambahkan unordered_map
dan menambahkannya ke versi standar C ++.
map
umumnya pohon yang seimbang adalah karena digunakan operator<()
sebagai alat untuk menentukan lokasi.
map
diimplementasikan dari balanced binary search tree
(biasanya a rb_tree
), karena semua anggota di balanced binary search tree
diurutkan begitu juga dengan map;
hash_map
diimplementasikan dari. hashtable
Karena semua hashtable
anggota dalam hash_map(unordered_map)
tidak diurutkan sehingga anggota dalam tidak diurutkan.
hash_map
bukan pustaka standar c ++, tetapi sekarang diubah namanya menjadi unordered_map
(Anda dapat menganggapnya berganti nama) dan menjadi pustaka standar c ++ sejak c ++ 11 lihat pertanyaan ini Perbedaan antara hash_map dan unordered_map? untuk lebih detail.
Di bawah ini saya akan memberikan beberapa antarmuka inti dari kode sumber tentang bagaimana peta tipe dua diimplementasikan.
Kode di bawah ini hanya untuk menunjukkan bahwa, map hanyalah pembungkus dari sebuah balanced binary search tree
, hampir semua fungsinya hanya memanggil balanced binary search tree
fungsi tersebut.
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
diimplementasikan dari hashtable
yang strukturnya agak seperti ini:
Pada kode di bawah ini, saya akan memberikan bagian utama dari hashtable
, dan kemudian memberikan 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);
};
Seperti map's
hanya anggota rb_tree
, hash_map's
satu - satunya anggota hashtable
. Itu kode utama seperti di bawah ini:
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);
};
};
Gambar di bawah ini menunjukkan ketika hash_map memiliki 53 keranjang, dan memasukkan beberapa nilai, struktur internalnya.
Gambar di bawah ini menunjukkan beberapa perbedaan antara map dan hash_map (unordered_map), gambar berasal dari Bagaimana memilih antara map dan unordered_map? :
Saya tidak tahu apa yang memberi, tetapi, hash_map membutuhkan lebih dari 20 detik untuk menghapus () 150K kunci integer unsigned dan nilai float. Saya hanya menjalankan dan membaca kode orang lain.
Beginilah cara menyertakan hash_map.
#include "StdAfx.h"
#include <hash_map>
Saya membaca ini di sini https://bytes.com/topic/c/answers/570079-perfomance-clear-vs-swap
mengatakan bahwa clear () adalah urutan O (N). Bagi saya, itu sangat aneh, tapi begitulah adanya.