C ++ 0x memperkenalkan unordered_set
yang tersedia di boost
dan banyak tempat lain. Apa yang saya mengerti adalah bahwa unordered_set
tabel hash dengan O(1)
kompleksitas pencarian. Di sisi lain, set
tidak lain adalah pohon dengan log(n)
kompleksitas pencarian. Mengapa di bumi ada orang yang menggunakan set
bukan unordered_set
? yaitu apakah ada kebutuhan untuk set
lagi?
145
Jawaban:
Ketika, untuk seseorang yang ingin mengulangi item set, urutan penting.
sumber
< >
?Set yang tidak dipesan harus membayar waktu akses rata-rata O (1) dalam beberapa cara:
set
menggunakan lebih sedikit memori daripadaunordered_set
menyimpan jumlah elemen yang sama.set
mungkin lebih cepat daripada pencarian dalamunordered_set
.unordered_set
, mereka sering dijamin memiliki lebih baik kompleksitas kasus terburuk untukset
(misalnyainsert
).set
macam unsur-unsur berguna jika Anda ingin akses mereka dalam rangka.set
s dengan<
,<=
,>
dan>=
.unordered_set
Tidak diperlukan untuk mendukung operasi ini.sumber
<
).Setiap kali Anda lebih suka pohon ke tabel hash.
Misalnya, tabel hash adalah "O (n)" di kasus terburuk. O (1) adalah kasus rata-rata. Pohon adalah "O ( log n)" paling buruk.
sumber
Gunakan setel saat:
Gunakan unordered_set saat:
Contoh:
set:
Input: 1, 8, 2, 5, 3, 9
Output: 1, 2, 3, 5, 8, 9
Unordered_set:
Input: 1, 8, 2, 5, 3, 9
Output: 9 3 1 8 2 5 (mungkin urutan ini, dipengaruhi oleh fungsi hash)
Terutama perbedaan:
Catatan: (dalam beberapa kasus
set
lebih mudah) misalnya menggunakanvector
sebagai kunciAlasan mengapa
vector<int>
bisa menjadi kunciset
karenavector
menimpaoperator<
.Tetapi jika Anda menggunakan
unordered_set<vector<int>>
Anda harus membuat fungsi hashvector<int>
, karena vektor tidak memiliki fungsi hash, jadi Anda harus mendefinisikan satu seperti:Anda dapat melihat bahwa dalam beberapa kasus
unordered_set
lebih rumit.Dikutip dari: https://www.geeksforgeeks.org/set-vs-unordered_set-c-stl/ https://stackoverflow.com/a/29855973/6329006
sumber
Karena std :: set adalah bagian dari Standard C ++ dan unordered_set tidak. C ++ 0x BUKAN standar, dan tidak juga Meningkatkan. Bagi banyak dari kita, portabilitas sangat penting, dan itu berarti berpegang teguh pada standar.
sumber
Pertimbangkan algoritma Sweepline. Algoritma ini akan gagal total dengan tabel hash, tetapi bekerja dengan indah dengan pohon seimbang. Untuk memberi Anda contoh konkret dari algoritma sweepline pertimbangkan algoritma fortune. http://en.wikipedia.org/wiki/Fortune%27s_algorithm
sumber
Satu hal lagi, selain apa yang sudah disebutkan orang lain. Sementara kompleksitas amortisasi yang diharapkan untuk memasukkan elemen ke unordered_set adalah O (1), setiap sekarang dan kemudian akan membutuhkan O (n) karena tabel hash perlu direstrukturisasi (jumlah ember perlu diubah) - bahkan dengan fungsi hash 'baik'. Sama seperti memasukkan elemen ke vektor membutuhkan O (n) setiap saat karena array yang mendasarinya perlu dialokasikan kembali.
Memasukkan dalam set selalu membutuhkan paling banyak O (log n). Ini mungkin lebih disukai di beberapa aplikasi.
sumber
Maafkan saya, satu hal lagi yang perlu diperhatikan tentang properti yang diurutkan:
Jika Anda ingin rentang data dalam wadah, misalnya: Anda menyimpan waktu dalam set , dan Anda ingin waktu dari 2013-01-01 hingga 2014-01-01.
Untuk unordered_set tidak mungkin.
Tentu saja, contoh ini akan lebih meyakinkan untuk kasus penggunaan antara peta dan unordered_map .
sumber
g++
6.4 stdlibc ++ memerintahkan vs patokan set tidak teraturSaya membandingkan penerapan Linux C ++ yang dominan ini untuk melihat perbedaannya:
Rincian dan analisis benchmark lengkap telah diberikan di: Apa struktur data yang mendasari set STL di C ++? dan saya tidak akan mengulanginya di sini.
"BST" berarti "diuji dengan
std::set
dan" peta hash "berarti" diuji denganstd::unordered_set
. "Heap" untukstd::priority_queue
yang saya analisis di: Heap vs Binary Search Tree (BST)Sebagai ringkasan cepat:
grafik dengan jelas menunjukkan bahwa dalam kondisi ini, penyisipan hashmap selalu jauh lebih cepat ketika ada lebih dari 100k item, dan perbedaannya bertambah ketika jumlah item meningkat
Biaya peningkatan kecepatan ini adalah Anda tidak dapat melakukan traverse secara efisien.
kurva jelas menunjukkan bahwa dipesan
std::set
adalah berbasis BST danstd::unordered_set
berbasis hashmap. Dalam jawaban referensi, saya selanjutnya mengonfirmasi bahwa dengan langkah GDB men-debug kode.Pertanyaan serupa untuk
map
vsunordered_map
: Apakah ada keuntungan menggunakan peta di atas unordered_map jika ada kunci sepele?sumber
Tentu saja, saya akan mengatakan itu nyaman untuk memiliki sesuatu dalam suatu hubungan jika Anda ingin mengubahnya menjadi format yang berbeda.
Ada juga kemungkinan bahwa sementara satu lebih cepat diakses, waktu untuk membangun indeks atau memori yang digunakan saat membuat dan / atau mengaksesnya lebih besar.
sumber
Jika Anda ingin memiliki hal-hal yang diurutkan, maka Anda akan menggunakan set alih-alih unordered_set. unordered_set digunakan lebih dari set ketika memesan disimpan tidak masalah.
sumber
Meskipun jawaban ini mungkin terlambat 10 tahun, ada baiknya menunjukkan bahwa
std::unordered_set
juga memiliki kelemahan keamanan.Jika fungsi hash dapat diprediksi (hal ini biasanya terjadi kecuali jika menerapkan tindakan balasan seperti garam acak), penyerang dapat mengolah data yang menghasilkan tabrakan hash dan menyebabkan semua penyisipan dan pencarian membutuhkan waktu O (n) .
Ini dapat digunakan untuk serangan penolakan layanan yang sangat efisien dan elegan.
Banyak (kebanyakan?) Implementasi bahasa yang menggunakan peta hash secara internal telah mengalami hal ini:
sumber