Mengapa seseorang ingin menggunakan daftar tertaut di atas array?
Pengkodean daftar-tertaut, tidak diragukan lagi, sedikit lebih banyak bekerja daripada menggunakan array dan orang mungkin bertanya-tanya apa yang akan membenarkan upaya tambahan.
Saya pikir penyisipan elemen baru adalah sepele dalam daftar-tertaut tapi itu adalah tugas utama dalam sebuah array. Apakah ada keuntungan lain dari menggunakan daftar tertaut untuk menyimpan satu set data dibandingkan menyimpannya dalam array?
Pertanyaan ini bukan duplikat dari pertanyaan ini karena pertanyaan lain adalah menanyakan secara khusus tentang kelas Java tertentu sementara pertanyaan ini berkaitan dengan struktur data umum.
arrays
data-structures
linked-list
language-agnostic
Onorio Catenacci
sumber
sumber
Jawaban:
sumber
Alasan bagus lainnya adalah bahwa daftar tertaut cocok untuk implementasi multi-utas yang efisien. Alasan untuk ini adalah bahwa perubahan cenderung bersifat lokal - hanya mempengaruhi satu atau dua penunjuk untuk disisipkan dan dihapus pada bagian lokal dari struktur data. Jadi, Anda dapat memiliki banyak utas yang bekerja pada daftar tertaut yang sama. Terlebih lagi, dimungkinkan untuk membuat versi bebas-kunci menggunakan operasi tipe-CAS dan menghindari kunci yang berat sama sekali.
Dengan daftar tertaut, iterator juga dapat melintasi daftar saat modifikasi sedang terjadi. Dalam kasus optimis di mana modifikasi tidak berbenturan, iterator dapat berlanjut tanpa pertengkaran.
Dengan sebuah array, setiap perubahan yang memodifikasi ukuran array cenderung membutuhkan penguncian sebagian besar array dan pada kenyataannya, jarang terjadi hal ini dilakukan tanpa kunci global di seluruh array sehingga modifikasi menjadi penghentian urusan dunia.
sumber
ConcurrentSkipListMap
atauConcurrentSkipListMap
bukan daftar, bahkan jika "Daftar" muncul di suatu tempat atas namanya. Keduanya membutuhkan kunci yang akan diurutkan dan unik. Jika Anda memerlukanList
, yaitu struktur data yang memungkinkan elemen duplikat dalam urutan acak, itu tidak cocok dan Anda harus berusaha keras untuk membuat struktur data sepertiLinkedList
hal yang dapat diperbarui secara bersamaan. Jika Anda hanya perlu antrian atau deque bersamaan, ya, bahkan ada contoh yang ada, tetapi konkurenList
... Saya tidak yakin bahwa ini bahkan mungkin.Wikipedia memiliki bagian yang sangat bagus tentang perbedaannya.
http://en.wikipedia.org/wiki/Linked_list
sumber
Saya akan menambahkan yang lain - daftar dapat bertindak sebagai struktur data yang berfungsi murni .
Misalnya, Anda dapat memiliki daftar yang sama sekali berbeda berbagi bagian akhir yang sama
yaitu:
tanpa harus menyalin data yang ditunjuk oleh
a
keb
danc
.Inilah sebabnya mengapa mereka sangat populer dalam bahasa fungsional, yang menggunakan variabel tidak berubah -
prepend
dantail
operasi dapat terjadi secara bebas tanpa harus menyalin data asli - fitur yang sangat penting ketika Anda memperlakukan data sebagai tidak dapat diubah.sumber
Selain memasukkan ke tengah daftar menjadi lebih mudah - juga jauh lebih mudah untuk menghapus dari tengah daftar yang ditautkan daripada array.
Tapi sejujurnya, saya tidak pernah menggunakan daftar tertaut. Setiap kali saya membutuhkan penyisipan dan penghapusan cepat, saya juga membutuhkan pencarian cepat, jadi saya pergi ke HashSet atau Kamus.
sumber
Menggabungkan dua daftar tertaut (terutama dua daftar tertaut dua kali lipat) jauh lebih cepat daripada menggabungkan dua array (dengan asumsi penggabungan itu merusak). Yang pertama mengambil O (1), yang terakhir mengambil O (n).
EDIT: Untuk memperjelas, maksud saya "penggabungan" di sini dalam arti tidak tertata, bukan seperti dalam penggabungan. Mungkin "menyatukan" akan menjadi kata yang lebih baik.
sumber
Argumen yang secara luas tidak dihargai untuk ArrayList dan terhadap LinkedList adalah bahwa LinkedLists tidak nyaman saat melakukan debugging . Waktu yang dihabiskan oleh pengembang pemeliharaan untuk memahami program, misalnya untuk menemukan bug, meningkat dan IMHO kadang-kadang tidak membenarkan nanodetik dalam peningkatan kinerja atau byte dalam konsumsi memori dalam aplikasi perusahaan. Terkadang (well, tentu saja itu tergantung pada jenis aplikasi), lebih baik membuang beberapa byte tetapi memiliki aplikasi yang lebih mudah dirawat atau lebih mudah dipahami.
Misalnya, di lingkungan Java dan menggunakan Eclipse debugger, debugging ArrayList akan mengungkapkan struktur yang sangat mudah dipahami:
Di sisi lain, menonton konten LinkedList dan menemukan objek tertentu menjadi mimpi buruk mengklik Expand-The-Tree, belum lagi overhead kognitif yang diperlukan untuk menyaring internal LinkedList:
sumber
Pertama-tama, di C ++ linked-list seharusnya tidak lebih banyak kesulitan untuk dikerjakan daripada sebuah array. Anda dapat menggunakan std :: list atau daftar penambah boost untuk daftar tertaut. Masalah utama dengan daftar tertaut vs array adalah ruang tambahan yang diperlukan untuk pointer dan akses acak yang mengerikan. Anda harus menggunakan daftar tertaut jika Anda
sumber
Bagi saya itu seperti ini,
Mengakses
Penyimpanan
Ukuran
Penyisipan / Penghapusan
sumber
Dua hal:
Jangan pernah kode kode daftar tertaut saat menggunakan C ++. Cukup gunakan STL. Betapa sulitnya untuk mengimplementasikan seharusnya tidak pernah menjadi alasan untuk memilih satu struktur data daripada yang lain karena sebagian besar sudah diterapkan di sana.
Adapun perbedaan aktual antara array dan daftar tertaut, hal besar bagi saya adalah bagaimana Anda berencana menggunakan struktur. Saya akan menggunakan vektor istilah karena itulah istilah untuk array yang dapat diubah ukurannya dalam C ++.
Pengindeksan ke daftar tertaut lambat karena Anda harus melintasi daftar untuk mendapatkan indeks yang diberikan, sementara vektor bersebelahan dalam memori dan Anda bisa sampai di sana menggunakan pointer matematika.
Menambahkan ke akhir atau awal daftar tertaut itu mudah, karena Anda hanya perlu memperbarui satu tautan, di mana dalam vektor Anda mungkin harus mengubah ukuran dan menyalin isinya.
Menghapus item dari daftar itu mudah, karena Anda hanya perlu memutuskan sepasang tautan dan kemudian memasangnya kembali. Menghapus item dari vektor bisa lebih cepat atau lebih lambat, tergantung apakah Anda peduli dengan pesanan. Menukar item terakhir dari atas item yang ingin Anda hapus lebih cepat, sementara menggeser semuanya setelah lebih lambat tetapi tetap memesan.
sumber
Eric Lippert baru-baru ini memposting di salah satu alasan mengapa array harus digunakan secara konservatif.
sumber
Penyisipan dan penghapusan cepat memang argumen terbaik untuk daftar tertaut. Jika struktur Anda tumbuh secara dinamis dan akses waktu konstan ke elemen apa pun tidak diperlukan (seperti tumpukan dinamis dan antrian), daftar tertaut adalah pilihan yang baik.
sumber
Ini yang cepat: Penghapusan item lebih cepat.
sumber
Linked-list sangat berguna ketika koleksi terus tumbuh & menyusut. Misalnya, sulit membayangkan mencoba menerapkan Antrian (tambahkan ke akhir, hapus dari depan) menggunakan sebuah array - Anda akan menghabiskan seluruh waktu Anda untuk mengubah segalanya. Di sisi lain, itu sepele dengan daftar-tertaut.
sumber
Selain menambah dan menghapus dari tengah daftar, saya lebih suka daftar tertaut karena mereka dapat tumbuh dan menyusut secara dinamis.
sumber
Tidak ada yang pernah mengkode daftar tertaut mereka lagi. Itu konyol. Premis bahwa menggunakan daftar tertaut membutuhkan lebih banyak kode sama sekali salah.
Saat ini, membuat daftar tertaut hanyalah latihan untuk siswa sehingga mereka dapat memahami konsep tersebut. Sebagai gantinya, semua orang menggunakan daftar yang dibuat sebelumnya. Dalam C ++, berdasarkan pada deskripsi di pertanyaan kami, itu mungkin berarti vektor stl (
#include <vector>
).Oleh karena itu, memilih daftar yang ditautkan vs sebuah array sepenuhnya tentang menimbang karakteristik yang berbeda dari setiap struktur relatif terhadap kebutuhan aplikasi Anda. Mengatasi beban pemrograman tambahan harus memiliki dampak nol pada keputusan.
sumber
Ini benar-benar masalah efisiensi, overhead untuk memasukkan, menghapus atau memindahkan (di mana Anda tidak hanya bertukar) elemen dalam daftar tertaut minimal, yaitu operasi itu sendiri adalah O (1), ayat O (n) untuk sebuah array. Ini dapat membuat perbedaan yang signifikan jika Anda banyak beroperasi pada daftar data. Anda memilih tipe data Anda berdasarkan pada bagaimana Anda akan beroperasi pada mereka dan memilih yang paling efisien untuk algoritma yang Anda gunakan.
sumber
Array masuk akal di mana jumlah item yang tepat akan diketahui, dan di mana pencarian berdasarkan indeks masuk akal. Misalnya, jika saya ingin menyimpan keadaan yang tepat dari output video saya pada saat tertentu tanpa kompresi saya mungkin akan menggunakan array ukuran [1024] [768]. Ini akan memberi saya apa yang saya butuhkan, dan daftar akan jauh lebih lambat untuk mendapatkan nilai piksel yang diberikan. Di tempat-tempat di mana array tidak masuk akal, biasanya ada tipe data yang lebih baik daripada daftar untuk menangani data secara efektif.
sumber
Array Vs Linked List:
sumber
karena array bersifat statis, oleh karena itu semua operasi seperti alokasi memori hanya terjadi pada saat kompilasi. Jadi prosesor harus mengurangi upaya pada saat runtime.
sumber
Misalkan Anda memiliki set yang dipesan, yang juga ingin Anda modifikasi dengan menambahkan dan menghapus elemen. Selanjutnya, Anda membutuhkan kemampuan untuk mempertahankan referensi ke suatu elemen sedemikian rupa sehingga nantinya Anda bisa mendapatkan elemen sebelumnya atau berikutnya. Misalnya, daftar tugas atau kumpulan paragraf dalam sebuah buku.
Pertama-tama kita harus mencatat bahwa jika Anda ingin mempertahankan referensi ke objek di luar set itu sendiri, Anda mungkin akan berakhir menyimpan pointer dalam array, daripada menyimpan objek itu sendiri. Kalau tidak, Anda tidak akan bisa memasukkan ke dalam array - jika objek tertanam ke dalam array mereka akan bergerak selama penyisipan dan setiap pointer ke mereka akan menjadi tidak valid. Hal yang sama berlaku untuk indeks array.
Masalah pertama Anda, seperti yang telah Anda catat sendiri, adalah daftar yang terhubung dengan penyisipan memungkinkan penyisipan dalam O (1), tetapi sebuah array umumnya membutuhkan O (n). Masalah ini sebagian dapat diatasi - dimungkinkan untuk membuat struktur data yang memberikan antarmuka akses by-ordinal seperti array di mana baik membaca dan menulis, paling buruk, logaritmik.
Masalah kedua Anda, dan lebih parah adalah bahwa elemen yang diberikan menemukan elemen berikutnya adalah O (n). Jika set tidak diubah, Anda bisa mempertahankan indeks elemen sebagai referensi alih-alih pointer sehingga membuat operasi find-next O (1), tetapi karena yang Anda miliki hanyalah pointer ke objek itu sendiri dan tidak mungkin untuk menentukan indeks saat ini dalam array selain dengan memindai seluruh "array". Ini adalah masalah yang tidak dapat diatasi untuk array - bahkan jika Anda dapat mengoptimalkan penyisipan, tidak ada yang dapat Anda lakukan untuk mengoptimalkan operasi tipe find-next.
sumber
Dalam sebuah array Anda memiliki hak istimewa untuk mengakses elemen apa pun dalam waktu O (1). Jadi itu cocok untuk operasi seperti Pencarian biner, Pengurutan cepat, dll. Daftar tertaut di sisi lain cocok untuk penghapusan penyisipan seperti pada waktu O (1). Keduanya memiliki kelebihan maupun kekurangan dan lebih memilih satu daripada yang lainnya bermuara pada apa yang ingin Anda terapkan.
- Pertanyaan yang lebih besar adalah bisakah kita memiliki hibrida keduanya. Sesuatu seperti apa yang python dan perl terapkan sebagai daftar.
sumber
Daftar Tertaut
Ini lebih disukai ketika menyangkut penyisipan! Pada dasarnya apa yang dilakukan adalah berurusan dengan pointer
1 -> 3 -> 4
Sisipkan (2)
1 ........ 3 ...... 4
..... 2
Akhirnya
1 -> 2 -> 3 -> 4
Satu panah dari 2 poin di 3 dan panah 1 poin di 2
Sederhana!
Tapi dari Array
| 1 | 3 | 4 |
Sisipkan (2) | 1 | 3 | | 4 | | 1 | | 3 | 4 | | 1 | 2 | 3 | 4 |
Yah siapa pun dapat memvisualisasikan perbedaannya! Hanya untuk 4 indeks kami melakukan 3 langkah
Bagaimana jika panjang array satu juta lalu? Apakah array efisien? Jawabannya adalah tidak! :)
Hal yang sama berlaku untuk penghapusan! Di Linked List kita cukup menggunakan pointer dan membatalkan elemen dan selanjutnya di kelas objek! Tetapi untuk array, kita perlu melakukan shiftLeft ()
Semoga itu bisa membantu! :)
sumber
Linked List lebih merupakan overhead untuk mempertahankan daripada array, juga membutuhkan penyimpanan memori tambahan semua poin ini disetujui. Tetapi ada beberapa hal yang tidak dapat dilakukan array. Dalam banyak kasus misalkan Anda menginginkan array dengan panjang 10 ^ 9 Anda tidak bisa mendapatkannya karena mendapatkan satu lokasi memori kontinu harus ada di sana. Daftar tertaut dapat menjadi penyelamat di sini.
Misalkan Anda ingin menyimpan banyak hal dengan data maka mereka dapat dengan mudah diperluas dalam daftar tertaut.
Wadah STL biasanya memiliki implementasi daftar terkait di belakang layar.
sumber
1- Daftar tertaut adalah struktur data dinamis sehingga dapat tumbuh dan menyusut pada saat runtime dengan mengalokasikan dan membatalkan alokasi memori. Jadi tidak perlu memberikan ukuran awal dari daftar tertaut. Penyisipan dan penghapusan node sangat mudah.
2 - ukuran daftar tertaut dapat meningkat atau menurun pada saat dijalankan sehingga tidak ada pemborosan memori. Dalam kasus array, ada banyak pemborosan memori, seperti jika kita mendeklarasikan array ukuran 10 dan menyimpan hanya 6 elemen di dalamnya maka ruang 4 elemen terbuang sia-sia. Tidak ada masalah dalam daftar tertaut karena memori hanya dialokasikan bila diperlukan.
3- Struktur data seperti tumpukan dan antrian dapat dengan mudah diimplementasikan menggunakan daftar tertaut.
sumber
Satu-satunya alasan untuk menggunakan daftar tertaut adalah memasukkan elemen itu mudah (menghapus juga).
Disadvatige bisa jadi bahwa pointer mengambil banyak ruang.
Dan tentang pengkodean itu lebih sulit: Biasanya Anda tidak perlu daftar kode tertaut (atau hanya sekali) mereka dimasukkan dalam STL dan tidak begitu rumit jika Anda masih harus melakukannya.
sumber
saya juga berpikir bahwa daftar tautan lebih baik daripada array. karena kami melakukan traverse di daftar tautan tetapi tidak di array
sumber
Bergantung pada bahasa Anda, beberapa kelemahan dan kelebihan ini dapat dipertimbangkan:
Bahasa Pemrograman C : Saat menggunakan daftar yang ditautkan (biasanya melalui pointer pointer), pertimbangan khusus harus dipastikan bahwa Anda tidak membocorkan memori. Seperti yang disebutkan sebelumnya, daftar tertaut mudah untuk diacak, karena semua yang dilakukan adalah mengubah pointer, tetapi apakah kita akan ingat untuk membebaskan semuanya?
Java : Java memiliki pengumpulan sampah otomatis, jadi memori yang bocor tidak akan menjadi masalah, tetapi disembunyikan dari pemrogram tingkat tinggi adalah detail implementasi dari apa itu daftar tertaut. Metode seperti menghapus simpul dari tengah daftar lebih rumit dari prosedur daripada yang diharapkan oleh beberapa pengguna bahasa.
sumber
Mengapa daftar yang ditautkan melalui array? Seperti yang telah dikatakan, kecepatan penyisipan dan penghapusan yang lebih besar
Tapi mungkin kita tidak harus hidup dengan batas baik, dan mendapatkan yang terbaik dari keduanya, pada saat yang sama ... eh?
Untuk penghapusan array, Anda dapat menggunakan byte 'Dihapus', untuk mewakili fakta bahwa sebuah baris telah dihapus, sehingga pengikatan ulang array tidak lagi diperlukan. Untuk meringankan beban penyisipan, atau mengubah data dengan cepat, gunakan daftar tertaut untuk itu. Kemudian ketika merujuk pada mereka, minta logika Anda untuk mencari yang pertama, lalu yang lainnya. Jadi, menggunakannya dalam kombinasi memberi Anda yang terbaik dari keduanya.
Jika Anda memiliki array yang sangat besar, Anda bisa menggabungkannya dengan yang lain, array yang jauh lebih kecil atau daftar tertaut di mana yang lebih kecil menampung 20, 50, 100 item yang paling terakhir digunakan. Jika yang dibutuhkan tidak ada dalam daftar atau array yang lebih pendek, Anda pergi ke array besar. Jika ditemukan di sana, Anda kemudian dapat menambahkannya ke daftar / larik yang lebih kecil dengan anggapan bahwa 'hal-hal yang paling baru digunakan paling mungkin untuk digunakan kembali' (dan ya, mungkin menabrak barang yang paling terakhir digunakan dari daftar). Yang benar dalam banyak kasus dan memecahkan masalah yang saya harus atasi dalam modul pemeriksaan izin .ASP keamanan, dengan mudah, elegan, dan kecepatan mengesankan.
sumber
Sementara banyak dari Anda telah menyentuh adv./dis utama dari daftar terkait array, sebagian besar perbandingan adalah bagaimana satu lebih baik / lebih buruk daripada yang lain. Anda dapat melakukan akses acak dalam array tetapi tidak mungkin dalam daftar tertaut dan lainnya. Namun, ini dengan asumsi daftar tautan dan larik akan diterapkan dalam aplikasi serupa. Namun jawaban yang benar adalah bagaimana daftar tautan akan lebih disukai daripada array dan sebaliknya dalam penyebaran aplikasi tertentu. Misalkan Anda ingin mengimplementasikan aplikasi kamus, apa yang akan Anda gunakan? Array: mmm itu akan memungkinkan pengambilan mudah melalui pencarian biner dan algo pencarian lainnya .. tapi mari kita pikirkan bagaimana daftar tautan bisa lebih baik .. Katakanlah Anda ingin mencari "Gumpalan" dalam kamus. Apakah masuk akal untuk memiliki daftar tautan A-> B-> C-> D ---->
Sekarang apakah pendekatan di atas lebih baik atau susunan datar [Adam, Apple, Banana, Blob, Cat, Cave]? Apakah mungkin dengan array? Jadi keuntungan utama dari daftar tautan adalah Anda dapat memiliki elemen tidak hanya menunjuk ke elemen berikutnya tetapi juga ke beberapa daftar tautan / array / heap / atau lokasi memori lainnya. Array adalah satu memori datar datar yang diiris menjadi ukuran blok elemen yang akan disimpannya. Daftar tautan di sisi lain adalah bongkahan unit memori non-darurat (dapat ukuran apa saja dan dapat menyimpan apa saja) dan menunjuk ke masing-masing selain yang Anda inginkan. Demikian pula katakanlah Anda sedang membuat drive USB. Sekarang apakah Anda ingin file disimpan sebagai array atau daftar tautan? Saya pikir Anda mendapatkan ide tentang apa yang saya tunjukkan :)
sumber