Saya telah membaca tentang wadah STL dalam buku saya tentang C ++, khususnya bagian tentang STL dan wadahnya. Sekarang saya mengerti masing-masing dan masing-masing dari mereka memiliki sifat khusus mereka sendiri, dan saya hampir menghafal mereka semua ... Tapi apa yang saya belum pahami adalah di mana skenario masing-masing digunakan.
Apa penjelasannya? Kode contoh lebih disukai.
c++
stl
container-data-type
Daniel Sloof
sumber
sumber
Jawaban:
Lembar cheat ini memberikan ringkasan yang cukup bagus dari berbagai wadah.
Lihat diagram alur di bagian bawah sebagai panduan untuk digunakan dalam berbagai skenario penggunaan:
Dibuat oleh David Moore dan berlisensi CC BY-SA 3.0
sumber
vector
daripada kosong. stackoverflow.com/questions/10699265/…unordered_map
danunordered_set
(dan berbagai varian mereka) yang tidak ada dalam bagan alur tetapi merupakan pilihan yang baik ketika Anda tidak peduli dengan pesanan tetapi perlu menemukan elemen dengan kunci. Pencarian mereka biasanya O (1) bukan O (log n).Berikut adalah diagram alur yang terinspirasi oleh versi David Moore (lihat di atas) yang saya buat, yang mutakhir (kebanyakan) dengan standar baru (C ++ 11). Ini hanya pendapat pribadi saya, itu tidak bisa dibantah, tapi saya pikir itu bisa berharga untuk diskusi ini:
sumber
vector (sorted)
agak tidak konsisten dengan yang lain. Ini bukan jenis wadah yang berbeda, hanya sajastd::vector
tetapi disortir. Yang lebih penting, saya tidak melihat mengapa seseorang tidak dapat menggunakanstd::set
iterasi yang diperintahkan jika itu adalah perilaku standar iterasi melalui set. Tentu, jika jawabannya adalah berbicara tentang mengakses nilai-nilai wadah melalui tertib[]
, maka ok Anda hanya dapat melakukannya dengan sotedstd::vector
. Namun dalam kedua kasus tersebut, keputusan harus diambil tepat setelah pertanyaan "diperlukan"Jawaban sederhana: gunakan
std::vector
untuk semuanya kecuali Anda memiliki alasan kuat untuk melakukan sebaliknya.Ketika Anda menemukan kasus di mana Anda berpikir, "Wah,
std::vector
tidak berfungsi dengan baik di sini karena X", lanjutkan berdasarkan X.sumber
std::remove_if
hampir selalu lebih unggul daripada pendekatan "delete during iteration".Lihatlah Efektif STL oleh Scott Meyers. Ada baiknya menjelaskan cara menggunakan STL.
Jika Anda ingin menyimpan sejumlah objek yang ditentukan / tidak ditentukan dan Anda tidak akan pernah menghapusnya, maka vektorlah yang Anda inginkan. Ini adalah pengganti default untuk array C, dan berfungsi seperti itu, tetapi tidak meluap. Anda dapat mengatur ukurannya sebelumnya juga dengan cadangan ().
Jika Anda ingin menyimpan jumlah objek yang tidak ditentukan, tetapi Anda akan menambahkan dan menghapusnya, maka Anda mungkin menginginkan daftar ... karena Anda dapat menghapus elemen tanpa memindahkan elemen berikut - tidak seperti vektor. Namun, dibutuhkan lebih banyak memori daripada vektor, dan Anda tidak dapat mengakses elemen secara berurutan.
Jika Anda ingin mengambil banyak elemen dan hanya menemukan nilai unik dari elemen tersebut, membacanya semuanya menjadi satu set akan melakukannya, dan itu akan mengurutkannya untuk Anda juga.
Jika Anda memiliki banyak pasangan nilai kunci, dan Anda ingin mengurutkannya berdasarkan kunci, maka peta itu berguna ... tetapi itu hanya akan menampung satu nilai per kunci. Jika Anda membutuhkan lebih dari satu nilai per kunci, Anda bisa memiliki vektor / daftar sebagai nilai Anda di peta, atau menggunakan multimap.
Itu tidak ada di STL, tetapi ada di pembaruan TR1 ke STL: jika Anda memiliki banyak pasangan nilai kunci yang akan Anda cari dengan kunci, dan Anda tidak peduli dengan pesanan mereka, Anda mungkin ingin menggunakan hash - yaitu tr1 :: unordered_map. Saya telah menggunakannya dengan Visual C ++ 7.1, di mana ia disebut stdext :: hash_map. Ini memiliki pencarian O (1) bukan pencarian O (log n) untuk peta.
sumber
hash_map
bukanlah implementasi yang sangat baik. Saya berharap mereka melakukan yang lebih baikunordered_map
.list
dilakukan. Agak mencolok kesalahan di sana.Saya mendesain ulang diagram alur untuk memiliki 3 properti:
Diagram alir:
Info lebih lanjut disediakan di tautan ini .
sumber
Poin penting hanya sebentar disebutkan sejauh ini, adalah bahwa jika Anda memerlukan memori yang berdekatan (seperti array C memberikan), maka Anda dapat hanya menggunakan
vector
,array
ataustring
.Gunakan
array
jika ukuran diketahui pada waktu kompilasi.Gunakan
string
jika Anda hanya perlu bekerja dengan tipe karakter dan membutuhkan string, bukan hanya wadah tujuan umum.Gunakan
vector
dalam semua kasus lain (vector
bagaimanapun juga harus menjadi pilihan default dari wadah).Dengan ketiganya, Anda dapat menggunakan
data()
fungsi anggota untuk mendapatkan pointer ke elemen pertama wadah.sumber
Itu semua tergantung pada apa yang ingin Anda simpan dan apa yang ingin Anda lakukan dengan wadah. Berikut adalah beberapa (sangat tidak lengkap) contoh untuk kelas kontainer yang paling sering saya gunakan:
vector
: Tata letak yang ringkas dengan sedikit atau tanpa overhead memori per objek yang terkandung. Efisien untuk diulangi. Menambahkan, menyisipkan, dan menghapus bisa mahal, terutama untuk objek yang kompleks. Murah untuk menemukan objek yang terkandung oleh indeks, misalnya myVector [10]. Gunakan di mana Anda akan menggunakan array di C. Bagus di mana Anda memiliki banyak objek sederhana (misalnya int). Jangan lupa untuk menggunakanreserve()
sebelum menambahkan banyak objek ke wadah.list
: Overhead memori kecil per objek yang terkandung. Efisien untuk diulangi. Tambahkan, masukkan, dan hapus itu murah. Gunakan tempat Anda akan menggunakan daftar tertaut di C.set
(danmultiset
): overhead memori signifikan per objek yang terkandung. Gunakan tempat Anda perlu mencari tahu dengan cepat apakah wadah itu berisi objek yang diberikan, atau gabungkan wadah secara efisien.map
(danmultimap
): overhead memori signifikan per objek yang terkandung. Gunakan tempat Anda ingin menyimpan pasangan nilai kunci dan mencari nilai dengan kunci dengan cepat.Bagan alur pada lembar contekan yang disarankan oleh zdan menyediakan panduan yang lebih lengkap.
sumber
Satu pelajaran yang saya pelajari adalah: Cobalah untuk membungkusnya dalam kelas, karena mengubah jenis wadah suatu hari dapat menghasilkan kejutan besar.
Tidak perlu banyak biaya di muka, dan menghemat waktu dalam debugging ketika Anda ingin istirahat setiap kali seseorang melakukan operasi x pada struktur ini.
Datang untuk memilih struktur data yang sempurna untuk suatu pekerjaan:
Setiap struktur data menyediakan beberapa operasi, yang dapat beragam kompleksitas waktu:
O (1), O (lg N), O (N), dll.
Anda pada dasarnya harus mengambil tebakan terbaik, di mana operasi akan dilakukan paling banyak, dan menggunakan struktur data yang memiliki operasi itu sebagai O (1).
Sederhana, bukan (-:
sumber
auto myIterator = whateverCollection.begin(); // <-- immune to changes of container type
typedef Collection<Foo*> CollectionOfFoo;
cukup?Saya memperluas diagram alur Mikael Persson yang fantastis. Saya menambahkan beberapa kategori wadah, wadah array, dan beberapa catatan. Jika Anda ingin salinan Anda sendiri, inilah Gambar Google. Terima kasih, Mikael untuk melakukan pekerjaan dasar! C ++ Pemilih Kontainer
sumber
Saya menjawab ini dalam pertanyaan lain yang ditandai sebagai dup yang satu ini. Tetapi saya merasa senang untuk merujuk pada beberapa artikel bagus mengenai keputusan untuk memilih wadah standar.
Seperti @David Thornley menjawab, std :: vector adalah cara untuk pergi jika tidak ada kebutuhan khusus lainnya. Ini adalah saran yang diberikan oleh pencipta C ++, Bjarne Stroustrup di blog 2014.
Berikut ini tautan untuk artikel https://isocpp.org/blog/2014/06/stroustrup-lists
dan mengutip dari yang itu,
Dalam komentar tersebut, pengguna @NathanOliver juga menyediakan blog bagus lainnya, yang memiliki ukuran yang lebih konkret. https://baptiste-wicht.com/posts/2012/12/cpp-benchmark-vector-list-deque.html .
sumber