Bisakah Anda memikirkan alasan khusus mengapa penghapusan biasanya jauh lebih sulit untuk diterapkan daripada penyisipan untuk banyak (kebanyakan?) Struktur data?
Contoh cepat: daftar tertaut. Penyisipan itu sepele, tetapi penghapusan memiliki beberapa kasus khusus yang membuatnya lebih sulit. Pohon pencarian biner yang menyeimbangkan diri sendiri seperti AVL dan Merah-hitam adalah contoh klasik implementasi penghapusan yang menyakitkan.
Saya ingin mengatakan itu ada hubungannya dengan cara kebanyakan orang berpikir: lebih mudah bagi kita untuk mendefinisikan sesuatu secara konstruktif, yang mengarah dengan baik ke penyisipan yang mudah.
algorithms
data-structures
Leo Brito
sumber
sumber
pop
,extract-min
?Jawaban:
Ini lebih dari sekadar kondisi pikiran; ada alasan fisik (yaitu digital) mengapa penghapusan lebih sulit.
Ketika Anda menghapus, Anda meninggalkan lubang di mana sesuatu dulu. Istilah teknis untuk entropi yang dihasilkan adalah "fragmentasi." Dalam daftar tertaut, ini mengharuskan Anda untuk "menambal" simpul yang dihapus dan membatalkan alokasi memori yang digunakannya. Pada pohon biner, itu menyebabkan ketidakseimbangan pohon. Dalam sistem memori, ini menyebabkan memori tidak digunakan untuk sementara waktu jika blok yang baru dialokasikan lebih besar daripada blok yang ditinggalkan oleh penghapusan.
Singkatnya, penyisipan lebih mudah karena Anda bisa memilih di mana Anda akan memasukkan. Penghapusan lebih sulit karena Anda tidak dapat memperkirakan sebelumnya item mana yang akan dihapus.
sumber
Mengapa cenderung lebih sulit untuk dihapus daripada disisipkan? Struktur data dirancang lebih dengan mempertimbangkan penyisipan daripada penghapusan, dan memang seharusnya begitu.
Pertimbangkan ini - untuk menghapus sesuatu dari struktur data, itu harus ada di tempat pertama. Jadi, Anda perlu menambahkannya terlebih dahulu, yang berarti bahwa paling banyak Anda memiliki penghapusan sebanyak yang Anda miliki sisipan. Jika Anda mengoptimalkan struktur data untuk penyisipan, Anda dijamin akan mendapatkan setidaknya sebanyak manfaat seolah-olah telah dioptimalkan untuk dihapus.
Selain itu, apa gunanya menghapus setiap elemen secara berurutan? Mengapa tidak memanggil beberapa fungsi yang menghapusnya sekaligus (mungkin hanya dengan membuat yang baru)? Juga, struktur data paling berguna ketika mereka benar-benar mengandung sesuatu. Jadi kasus penghapusan sebanyak insersi, dalam praktiknya, tidak akan menjadi sangat umum.
Ketika Anda mengoptimalkan sesuatu, Anda ingin mengoptimalkan hal-hal yang paling banyak dilakukan dan yang paling lama. Dalam penggunaan normal, penghapusan elemen struktur data lebih jarang terjadi daripada penyisipan.
sumber
k
elemen dengan cukup cepat: membalikkan input dan bergabung dengan vektor yang ada -O(k log k + n)
. Maka Anda memiliki struktur dengan penyisipan yang cukup rumit tetapi mengonsumsiu
elemen-elemen top adalah sepele dan cepat. Ambil yang terakhiru
dan pindahkan ujung vektor. Padahal, jika ada yang membutuhkan hal seperti itu, aku akan terkutuk. Saya harap ini setidaknya memperkuat argumen Anda.Itu tidak sulit.
Dengan daftar tertaut ganda, saat Anda memasukkan, Anda akan mengalokasikan memori, dan kemudian Anda akan menghubungkan dengan kepala atau simpul sebelumnya, dan dengan ekor atau simpul berikutnya. Ketika Anda menghapus, Anda akan memutuskan tautan dari yang persis sama, dan kemudian membebaskan memori. Semua operasi ini simetris.
Ini mengasumsikan bahwa dalam kedua kasus Anda memiliki simpul untuk memasukkan / menghapus. (Dan dalam hal penyisipan, bahwa Anda juga memiliki simpul untuk disisipkan sebelumnya, jadi dengan cara, penyisipan dapat dianggap sebagai sedikit lebih rumit.) Jika Anda mencoba untuk menghapus tidak memiliki simpul untuk dihapus, tetapi payload dari node, maka tentu saja Anda harus terlebih dahulu mencari daftar payload, tapi itu bukan kekurangan penghapusan, bukan?
Dengan pohon seimbang, hal yang sama berlaku: pohon umumnya perlu menyeimbangkan segera setelah penyisipan dan juga segera setelah penghapusan. Merupakan ide bagus untuk mencoba dan hanya memiliki satu rutin penyeimbang, dan menerapkannya setelah setiap operasi, terlepas dari apakah itu penyisipan atau penghapusan. Jika Anda mencoba menerapkan penyisipan yang selalu membuat pohon seimbang, dan juga penghapusan yang selalu membuat pohon seimbang, tanpa keduanya memiliki rutinitas penyeimbang yang sama, Anda tidak perlu mempersulit hidup Anda.
Singkatnya, tidak ada alasan mengapa seseorang harus lebih keras daripada yang lain, dan jika Anda menemukan itu, maka sebenarnya mungkin Anda adalah korban dari kecenderungan (yang sangat manusiawi) untuk menemukan bahwa lebih alami untuk berpikir. konstruktif daripada subtraktif, artinya Anda mungkin menerapkan penghapusan dengan cara yang lebih rumit daripada yang seharusnya. Tapi itu masalah manusia. Dari sudut pandang matematika, tidak ada masalah.
sumber
Dalam hal run-time, melihat perbandingan kompleksitas waktu operasi struktur data di Wikipedia, perhatikan operasi insert dan delete memiliki kompleksitas yang sama. Operasi penghapusan diprofilkan ada penghapusan oleh indeks, di mana Anda memiliki referensi ke elemen struktur yang akan dihapus; penyisipan adalah dengan item. Semakin lama waktu berjalan untuk dihapus dalam praktik adalah karena Anda biasanya memiliki item untuk dihapus dan bukan indeksnya, sehingga Anda juga memerlukan operasi pencarian. Sebagian besar struktur data dalam tabel tidak memerlukan penemuan tambahan untuk memasukkan karena posisi penempatan tidak tergantung pada item, atau posisi ditentukan secara implisit selama penyisipan.
Adapun kompleksitas kognitif, ada jawaban dalam pertanyaan: kasus tepi. Penghapusan mungkin memiliki lebih banyak daripada penyisipan (ini belum ditetapkan dalam kasus umum). Namun, setidaknya beberapa kasus tepi ini dapat dihindari dalam desain tertentu (misalnya, memiliki simpul sentinel dalam daftar tertaut).
sumber
Di atas semua masalah yang disebutkan ada integritas referensial data yang terlibat. Untuk membangun struktur data yang paling tepat seperti database dalam SQL, integritas referensial Oracle sangat penting.
Untuk memastikan bahwa Anda tidak sengaja menghancurkannya, banyak hal yang berbeda ditemukan.
Misalnya kaskade pada penghapusan yang tidak hanya menghapus apa yang pernah Anda coba hapus tetapi juga memicu pembersihan data terkait.
Ini membersihkan database dari data sampah serta menjaga integritas data tetap utuh.
Misalnya Anda memiliki tabel dengan orang tua dan jenis sebagai catatan terkait di tabel kedua.
Di mana orang tua adalah tabel utama. Jika Anda tidak memiliki integritas referensial yang diperkuat, Anda dapat menghapus catatan apa pun di tabel mana pun dan nanti Anda tidak akan tahu cara mendapatkan informasi keluarga lengkap karena Anda memiliki data di tabel anak dan tidak ada apa pun di tabel induk.
Itu sebabnya pemeriksaan integritas referensial tidak akan membiarkan Anda menghapus catatan dari tabel induk sampai catatan dari tabel anak dibersihkan.
Dan itulah sebabnya di sebagian besar sumber data lebih sulit untuk menghapus data.
sumber