Saya perhatikan di Efektif STL itu
vektor adalah jenis urutan yang harus digunakan secara default.
Apa artinya? Tampaknya mengabaikan efisiensi vector
dapat melakukan apa saja.
Adakah yang bisa menawarkan saya skenario di mana vector
bukan merupakan opsi yang layak tetapi list
harus digunakan?
Jawaban:
Situasi di mana Anda ingin memasukkan banyak item ke mana saja tetapi akhir urutan berulang kali.
Lihat jaminan kompleksitas untuk setiap jenis wadah:
Apa jaminan kompleksitas dari kontainer standar?
sumber
list
telahpush_front
vektor:
daftar:
Secara umum, gunakan vektor ketika Anda tidak peduli apa jenis wadah berurutan yang Anda gunakan, tetapi jika Anda melakukan banyak penyisipan atau penghapusan ke dan dari mana saja di dalam wadah selain dari akhir, Anda akan ingin untuk menggunakan daftar. Atau jika Anda memerlukan akses acak, maka Anda akan menginginkan vektor, bukan daftar. Selain itu, ada beberapa contoh di mana Anda akan membutuhkan satu atau yang lain berdasarkan aplikasi Anda, tetapi secara umum, itu adalah pedoman yang baik.
sumber
reserve()
untuk mengurangi itu ke O (1). Menambahkan item baru ke daftar (mis. Tidak membuat splicing) melakukan O (n) alokasi toko gratis.list
membebaskan memori ketika Anda menghapus elemen, tetapivector
tidak. Avector
tidak mengurangi kapasitasnya ketika Anda mengurangi ukurannya, kecuali jika Anda menggunakanswap()
triknya.Jika Anda tidak perlu sering memasukkan elemen maka vektor akan lebih efisien. Ini memiliki lokasi cache CPU yang jauh lebih baik daripada daftar. Dengan kata lain, mengakses satu elemen membuatnya sangat mungkin bahwa elemen berikutnya ada dalam cache dan dapat diambil tanpa harus membaca RAM yang lambat.
sumber
Sebagian besar jawaban di sini kehilangan satu detail penting: untuk apa?
Apa yang ingin Anda simpan di wadahnya?
Jika ini adalah kumpulan dari
int
s, makastd::list
akan hilang dalam setiap skenario, terlepas dari apakah Anda dapat realokasi, Anda hanya menghapus dari depan, dll. Daftar lebih lambat untuk dilintasi, setiap penyisipan akan membuat Anda interaksi dengan pengalokasi. Akan sangat sulit untuk menyiapkan contoh, di manalist<int>
ketukanvector<int>
. Dan bahkan kemudian,deque<int>
mungkin lebih baik atau dekat, bukan hanya menggunakan daftar, yang akan memiliki overhead memori yang lebih besar.Namun, jika Anda berurusan dengan gumpalan data yang besar dan jelek - dan beberapa di antaranya - Anda tidak ingin menempatkan keseluruhan saat memasukkan, dan menyalin karena realokasi akan menjadi bencana - maka Anda mungkin, mungkin, lebih baik dengan
list<UglyBlob>
darivector<UglyBlob>
.Namun, jika Anda beralih ke
vector<UglyBlob*>
atau bahkanvector<shared_ptr<UglyBlob> >
, lagi - daftar akan tertinggal.Jadi, pola akses, jumlah elemen target dll masih mempengaruhi perbandingan, tetapi dalam pandangan saya - ukuran elemen - biaya penyalinan dll.
sumber
list<T>
adalah kemungkinansplice
dalam O (1) . Jika Anda perlu penyambungan waktu secara konstan, daftar mungkin juga merupakan struktur pilihan;)UglyBlob
- bahkan objek dengan hanya beberapa anggota string dapat dengan mudah menjadi mahal untuk disalin, sehingga realokasi akan dikenakan biaya. Juga: Jangan abaikan ruang di atas kepala yangvector
bisa menyebabkan pertumbuhan objek dengan ukuran beberapa lusin byte (jika Anda tidak bisa melakukannyareserve
di muka).vector<smart_ptr<Large>>
vslist<Large>
- Saya akan mengatakan, jika Anda membutuhkan akses acak ke elemen, ituvector
masuk akal. Jika Anda tidak memerlukan akses acak,list
sepertinya lebih sederhana dan harus berkinerja sama.Satu kemampuan khusus std :: list adalah splicing (menghubungkan atau memindahkan sebagian atau seluruh daftar ke daftar yang berbeda).
Atau mungkin jika konten Anda sangat mahal untuk disalin. Dalam kasus seperti itu, mungkin lebih murah, misalnya, untuk menyortir koleksi dengan daftar.
Perhatikan juga bahwa jika koleksinya kecil (dan isinya tidak terlalu mahal untuk disalin), vektor mungkin masih mengungguli daftar, bahkan jika Anda menyisipkan dan menghapus di mana saja. Daftar mengalokasikan setiap node secara individual, dan itu mungkin jauh lebih mahal daripada memindahkan beberapa objek sederhana.
Saya tidak berpikir ada aturan yang sangat sulit. Tergantung pada apa yang Anda ingin lakukan dengan wadah, serta seberapa besar Anda mengharapkan wadah dan jenis yang terkandung. Vektor umumnya mengalahkan daftar, karena ia mengalokasikan isinya sebagai satu blok bersebelahan (pada dasarnya array yang dialokasikan secara dinamis, dan dalam kebanyakan keadaan, array adalah cara paling efisien untuk menampung banyak hal).
sumber
list::size
belum tentu waktu yang konstan. Lihat stackoverflow.com/questions/228908/is-listsize-really-on dan gcc.gnu.org/ml/libstdc++/2005-11/msg00219.htmlsplice
antara daftar yang berbeda ditentukan sebagai kompleksitas linier dansize
secara khusus konstan. Jadi, untuk mengakomodasi pemula yang melakukan iteratesize
atau apa pun, seluruh kelas algoritma berada di luar jangkauan untuk STL, atau periode wadah yang "sesuai".Baik siswa kelas saya tampaknya tidak dapat menjelaskan kepada saya kapan lebih efektif menggunakan vektor, tetapi mereka terlihat cukup senang ketika menasihati saya untuk menggunakan daftar.
Ini adalah bagaimana saya memahaminya
Daftar : Setiap item berisi alamat ke elemen berikutnya atau sebelumnya, jadi dengan fitur ini, Anda dapat mengacak item, meskipun item tersebut tidak diurutkan, urutannya tidak akan berubah: efisien jika memori Anda terpecah-pecah. Tetapi itu juga memiliki keuntungan lain yang sangat besar: Anda dapat dengan mudah memasukkan / menghapus item, karena satu-satunya hal yang perlu Anda lakukan adalah mengubah beberapa petunjuk. Kekurangan: Untuk membaca item tunggal acak, Anda harus melompat dari satu item ke item lain hingga Anda menemukan alamat yang benar.
Vektor : Saat menggunakan vektor, memori jauh lebih teratur seperti array reguler: setiap item ke-n disimpan tepat setelah (ke-1) item ke-1 dan sebelum (ke-1) ke-ke-ke-1. Mengapa lebih baik daripada daftar? Karena itu memungkinkan akses acak cepat. Begini caranya: jika Anda tahu ukuran item dalam vektor, dan jika mereka berdekatan dalam memori, Anda dapat dengan mudah memprediksi di mana item ke-n berada; Anda tidak perlu menelusuri semua item dalam daftar untuk membaca yang Anda inginkan, dengan vektor, Anda langsung membacanya, dengan daftar yang tidak dapat Anda baca. Di sisi lain, modifikasi array vektor atau ubah nilainya jauh lebih lambat.
Daftar lebih tepat untuk melacak objek yang dapat ditambahkan / dihapus dalam memori. Vektor lebih tepat ketika Anda ingin mengakses elemen dari sejumlah besar item tunggal.
Saya tidak tahu bagaimana daftar dioptimalkan, tetapi Anda harus tahu bahwa jika Anda ingin akses baca cepat, Anda harus menggunakan vektor, karena seberapa baik STL mempercepat daftar, itu tidak akan lebih cepat dalam akses baca daripada vektor.
sumber
vector
disebabkan oleh mengubah ukurannya bisa lambat? kemudian setuju, tetapi dalam kasus di manareserve()
dapat digunakan, itu menghindari masalah itu.Pada dasarnya vektor adalah array dengan manajemen memori otomatis. Data berdekatan dalam memori. Mencoba memasukkan data di tengah adalah operasi yang mahal.
Dalam daftar, data disimpan di lokasi memori yang tidak terkait. Memasukkan di tengah tidak melibatkan menyalin beberapa data untuk memberikan ruang bagi yang baru.
Untuk menjawab lebih spesifik pertanyaan Anda, saya akan mengutip halaman ini
sumber
Kapan saja Anda tidak dapat membatalkan iterator.
sumber
deque
cukup.Ketika Anda memiliki banyak penyisipan atau penghapusan di tengah urutan. misal manajer memori.
sumber
Mempertahankan validitas iterator adalah salah satu alasan untuk menggunakan daftar. Lain adalah ketika Anda tidak ingin vektor untuk realokasi ketika mendorong item. Ini dapat dikelola dengan penggunaan cadangan yang cerdas (), tetapi dalam beberapa kasus mungkin lebih mudah atau lebih layak untuk hanya menggunakan daftar.
sumber
Saat Anda ingin memindahkan objek di antara kontainer, Anda bisa menggunakan
list::splice
.Sebagai contoh, algoritma partisi grafik mungkin memiliki jumlah objek konstan dibagi secara rekursif di antara jumlah kontainer yang meningkat. Objek harus diinisialisasi sekali dan selalu tetap di lokasi yang sama dalam memori. Ini jauh lebih cepat untuk mengatur ulang mereka dengan menata kembali daripada dengan merealokasi.
Sunting: saat pustaka bersiap untuk mengimplementasikan C ++ 0x, kasus umum penyambungan urutan ke dalam daftar menjadi kompleksitas linier dengan panjang urutan. Ini karena
splice
(sekarang) perlu mengulangi urutan untuk menghitung jumlah elemen di dalamnya. (Karena daftar perlu mencatat ukurannya.) Cukup menghitung dan menautkan kembali daftar masih lebih cepat daripada alternatif lain, dan menyambung seluruh daftar atau elemen tunggal adalah kasus khusus dengan kompleksitas konstan. Tetapi, jika Anda memiliki urutan panjang untuk sambungan, Anda mungkin harus mencari-cari wadah yang lebih baik, kuno, dan tidak sesuai.sumber
Satu-satunya aturan keras di mana
list
harus digunakan adalah di mana Anda perlu mendistribusikan pointer ke elemen wadah.Berbeda dengan dengan
vector
, Anda tahu bahwa memori elemen tidak akan dialokasikan kembali. Jika bisa maka Anda mungkin memiliki petunjuk untuk memori yang tidak digunakan, yang terbaik adalah tidak-tidak besar dan paling buruk aSEGFAULT
.(Secara teknis
vector
dari*_ptr
juga akan bekerja tetapi dalam kasus bahwa Anda menirulist
sehingga hanya semantik.)Aturan lunak lainnya harus dilakukan dengan kemungkinan masalah kinerja memasukkan elemen ke tengah wadah, di mana
list
lebih disukai.sumber
Sederhanakan-
Pada akhir hari ketika Anda bingung memilih wadah di C ++ gunakan gambar diagram alur ini (Ucapkan terima kasih kepada saya): - masukkan deskripsi gambar di sini
Vektor-
1. vektor didasarkan pada memori menular
2. vektor adalah cara untuk pergi untuk kumpulan data kecil
3. vektor melakukan tercepat saat melintasi pada kumpulan data
4. penghapusan penyisipan vektor lambat pada kumpulan data besar tetapi cepat untuk yang sangat kecil
List
1. daftar didasarkan pada memori heap
2. daftar adalah cara untuk pergi untuk sangat besar data set
3. daftar relatif lambat pada melintasi kecil data set tapi cepat pada data set besar
4. daftar penyisipan penghapusan cepat pada kumpulan data besar tetapi lambat pada yang lebih kecil
sumber
Daftar hanyalah pembungkus untuk Linkedlink ganda di stl, sehingga menawarkan fitur yang mungkin Anda harapkan dari d-linklist yaitu O (1) penyisipan dan penghapusan. Sedangkan vektor adalah urutan data yang menular yang berfungsi seperti array dinamis.PS- lebih mudah dilintasi.
sumber
Dalam hal vektor dan daftar , perbedaan utama yang muncul pada saya adalah sebagai berikut:
vektor
Vektor menyimpan elemen-elemennya dalam memori yang berdekatan. Oleh karena itu, akses acak dimungkinkan di dalam vektor yang berarti bahwa mengakses elemen vektor sangat cepat karena kita dapat dengan mudah mengalikan alamat basis dengan indeks item untuk mengakses elemen itu. Bahkan, hanya dibutuhkan O (1) atau waktu yang konstan untuk tujuan ini.
Karena vektor pada dasarnya membungkus sebuah array, setiap kali Anda memasukkan elemen ke dalam vektor (array dinamis), ia harus mengubah ukurannya sendiri dengan menemukan blok memori baru yang berdekatan untuk mengakomodasi elemen-elemen baru yang memakan waktu mahal.
Itu tidak mengkonsumsi memori ekstra untuk menyimpan pointer ke elemen lain di dalamnya.
daftar
Daftar menyimpan elemen-elemennya dalam memori yang tidak bersebelahan. Oleh karena itu, akses acak tidak dimungkinkan di dalam daftar yang berarti bahwa untuk mengakses elemen-elemennya kita harus menggunakan pointer dan melintasi daftar yang lebih lambat relatif terhadap vektor. Ini membutuhkan O (n) atau waktu linier yang lebih lambat dari O (1).
Karena daftar menggunakan memori yang tidak bersebelahan, waktu yang diperlukan untuk memasukkan elemen ke dalam daftar jauh lebih efisien daripada dalam hal rekan vektornya karena realokasi memori dihindari.
Mengkonsumsi memori ekstra untuk menyimpan pointer ke elemen sebelum dan sesudah elemen tertentu.
Jadi, mengingat perbedaan-perbedaan ini, kami biasanya mempertimbangkan memori , akses acak sering dan penyisipan untuk menentukan pemenang daftar vektor vs dalam skenario yang diberikan.
sumber
Daftar adalah Daftar Tertaut Ganda sehingga mudah untuk menyisipkan dan menghapus suatu elemen. Kita hanya perlu mengubah beberapa pointer, sedangkan dalam vektor jika kita ingin memasukkan elemen di tengah maka setiap elemen setelah itu harus bergeser satu indeks. Juga jika ukuran vektor penuh maka pertama-tama harus meningkatkan ukurannya. Jadi ini operasi yang mahal. Jadi dimanapun operasi penyisipan dan penghapusan harus dilakukan lebih sering dalam daftar kasus seperti itu harus digunakan.
sumber