Pustaka peta terurut menyediakan peta hash dan kumpulan hash yang mempertahankan urutan penyisipan dengan cara yang mirip dengan OrderedDict Python. Saat melakukan iterasi pada peta, nilai akan dikembalikan dalam urutan yang sama seperti saat dimasukkan.
Nilai-nilai disimpan secara berdekatan dalam struktur yang mendasarinya, tidak ada lubang di antara nilai-nilai bahkan setelah operasi penghapusan. Secara default, std::deque
digunakan untuk struktur ini, tetapi std::vector
juga dapat digunakan. Struktur ini dapat diakses langsung melalui metode values_container()
dan jika strukturnya adalah std::vector
, metode data()
juga disediakan untuk berinteraksi dengan mudah dengan C API. Ini memberikan iterasi yang cepat tetapi dengan kelemahan operasi penghapusan O(bucket_count). Fungsi O(1) pop_back()
dan O(1) unordered_erase()
tersedia. Jika penghapusan berurutan sering digunakan, disarankan untuk menggunakan struktur data lain.
Untuk mengatasi tabrakan pada hash, perpustakaan menggunakan pemeriksaan Robin Hood linier dengan penghapusan shift mundur.
Pustaka menyediakan perilaku yang mirip dengan std::deque/std::vector
dengan nilai unik tetapi dengan kompleksitas waktu rata-rata O(1) untuk pencarian dan kompleksitas waktu diamortisasi sebesar O(1) untuk penyisipan. Hal ini disebabkan oleh jejak memori yang sedikit lebih tinggi (8 byte per bucket secara default).
Dua kelas disediakan: tsl::ordered_map
dan tsl::ordered_set
.
Catatan : Pustaka menggunakan pangkat dua untuk ukuran susunan bucketnya guna memanfaatkan modulo cepat. Untuk kinerja yang baik, tabel hash memerlukan fungsi hash yang terdistribusi dengan baik. Jika Anda mengalami masalah kinerja, periksa fungsi hash Anda.
tsl::ordered_map
dari CMakeLists.txt.std::unordered_map
tetapi dengan penyisipan lebih cepat dan penggunaan memori lebih sedikit (lihat tolok ukur untuk detailnya).find
dengan tipe yang berbeda dari Key
(misalnya jika Anda memiliki peta yang menggunakan std::unique_ptr<foo>
sebagai kunci, Anda dapat menggunakan foo*
atau std::uintptr_t
sebagai parameter kunci untuk find
tanpa membuat std::unique_ptr<foo>
, lihat contoh).precalculated_hash
di API).serialize/deserialize
di API untuk detailnya).-fno-exceptions
di Clang dan GCC, tanpa opsi /EH
di MSVC atau cukup dengan mendefinisikan TSL_NO_EXCEPTIONS
). std::terminate
digunakan sebagai pengganti instruksi throw
ketika pengecualian dinonaktifkan.std::unordered_map
dan std::unordered_set
.std::unordered_map
tsl::ordered_map
mencoba memiliki antarmuka yang mirip dengan std::unordered_map
, tetapi ada beberapa perbedaan.
RandomAccessIterator
.std::vector
dan std::deque
(lihat API untuk detailnya). Jika Anda menggunakan std::vector
sebagai ValueTypeContainer
, Anda dapat menggunakan reserve()
untuk mengalokasikan sebagian ruang terlebih dahulu dan menghindari pembatalan iterator saat dimasukkan.erase()
yang lambat, memiliki kompleksitas O(bucket_count). Ada versi O(1) yang lebih cepat unordered_erase()
, tetapi merusak urutan penyisipan (lihat API untuk detailnya). O(1) pop_back()
juga tersedia.operator==
dan operator!=
bergantung pada urutan. Dua tsl::ordered_map
dengan nilai yang sama tetapi disisipkan dalam urutan berbeda tidak dapat dibandingkan sama.operator*()
dan operator->()
mengembalikan referensi dan pointer ke const std::pair<Key, T>
alih-alih std::pair<const Key, T>
membuat nilai T
tidak dapat dimodifikasi. Untuk mengubah nilai, Anda harus memanggil metode value()
dari iterator untuk mendapatkan referensi yang bisa diubah. Contoh: tsl::ordered_map< int , int > map = {{ 1 , 1 }, { 2 , 1 }, { 3 , 1 }};
for ( auto it = map.begin(); it != map.end(); ++it) {
// it->second = 2; // Illegal
it. value () = 2 ; // Ok
}
IndexType
, periksa API untuk detailnya.bucket_size
, bucket
, ...). Jaminan keamanan thread sama dengan std::unordered_map
(yaitu dimungkinkan untuk memiliki beberapa pembaca secara bersamaan tanpa penulis).
Perbedaan ini juga berlaku antara std::unordered_set
dan tsl::ordered_set
.
Jika tidak disebutkan sebaliknya, fungsi memiliki jaminan pengecualian yang kuat, lihat detailnya. Di bawah ini kami mencantumkan kasus-kasus di mana jaminan ini tidak diberikan.
Jaminan hanya diberikan jika ValueContainer::emplace_back
memiliki jaminan pengecualian yang kuat (yang berlaku untuk std::vector
dan std::deque
selama tipe T
bukan tipe move-only dengan konstruktor move yang dapat memunculkan pengecualian, lihat detailnya).
Fungsi tsl::ordered_map::erase_if
dan tsl::ordered_set::erase_if
hanya memiliki jaminan berdasarkan prasyarat yang tercantum dalam dokumentasinya.
Untuk menggunakan peta yang dipesan, cukup tambahkan direktori penyertaan ke jalur penyertaan Anda. Ini adalah perpustakaan khusus header .
Jika Anda menggunakan CMake, Anda juga dapat menggunakan target yang diekspor tsl::ordered_map
dari CMakeLists.txt dengan target_link_libraries
.
# Example where the ordered-map project is stored in a third-party directory
add_subdirectory (third-party/ordered-map)
target_link_libraries (your_target PRIVATE tsl::ordered_map)
Jika proyek telah diinstal melalui make install
, Anda juga dapat menggunakan find_package(tsl-ordered-map REQUIRED)
alih-alih add_subdirectory
.
Kode ini harus bekerja dengan kompiler yang memenuhi standar C++11 dan telah diuji dengan GCC 4.8.4, Clang 3.5.0, dan Visual Studio 2015.
Untuk menjalankan pengujian, Anda memerlukan pustaka Boost Test dan CMake.
git clone https://github.com/Tessil/ordered-map.git
cd ordered-map/tests
mkdir build
cd build
cmake ..
cmake --build .
./tsl_ordered_map_tests
API dapat ditemukan di sini.
# include < iostream >
# include < string >
# include < cstdlib >
# include < tsl/ordered_map.h >
# include < tsl/ordered_set.h >
int main () {
tsl::ordered_map< char , int > map = {{ ' d ' , 1 }, { ' a ' , 2 }, { ' g ' , 3 }};
map. insert ({ ' b ' , 4 });
map[ ' h ' ] = 5 ;
map[ ' e ' ] = 6 ;
map. erase ( ' a ' );
// {d, 1} {g, 3} {b, 4} {h, 5} {e, 6}
for ( const auto & key_value : map) {
std::cout << " { " << key_value. first << " , " << key_value. second << " } " << std::endl;
}
map. unordered_erase ( ' b ' );
// Break order: {d, 1} {g, 3} {e, 6} {h, 5}
for ( const auto & key_value : map) {
std::cout << " { " << key_value. first << " , " << key_value. second << " } " << std::endl;
}
for ( auto it = map. begin (); it != map. end (); ++it) {
// it->second += 2; // Not valid.
it. value () += 2 ;
}
if (map. find ( ' d ' ) != map. end ()) {
std::cout << " Found 'd'. " << std::endl;
}
const std:: size_t precalculated_hash = std::hash< char >()( ' d ' );
// If we already know the hash beforehand, we can pass it as argument to speed-up the lookup.
if (map. find ( ' d ' , precalculated_hash) != map. end ()) {
std::cout << " Found 'd' with hash " << precalculated_hash << " . " << std::endl;
}
tsl::ordered_set< char , std::hash< char >, std::equal_to< char >,
std::allocator< char >, std::vector< char >> set;
set. reserve ( 6 );
set = { ' 3 ' , ' 4 ' , ' 9 ' , ' 2 ' };
set. erase ( ' 2 ' );
set. insert ( ' 1 ' );
set. insert ( '