Kelas-kelas struktur data apa yang bisa dibuat tetap?

19

Struktur data yang persisten adalah struktur data yang tidak dapat diubah. Operasi pada mereka mengembalikan "salinan" baru dari struktur data, tetapi diubah oleh operasi; struktur data lama tetap tidak berubah. Efisiensi umumnya dicapai dengan membagikan beberapa data yang mendasarinya, dan menghindari penyalinan penuh dari struktur data.

Pertanyaan:

  • Apakah ada hasil tentang kelas-kelas struktur data yang dapat dibuat tetap (tetap menjaga kompleksitas yang sama atau sangat mirip)?

  • Bisakah semua struktur data dibuat tetap (sambil mempertahankan kompleksitas yang sama atau sangat mirip)?

  • Apakah ada struktur data yang diketahui tidak dapat dibuat terus-menerus (sambil mempertahankan kompleksitas yang sama atau sangat mirip)?

Realz Slaw
sumber
1
Anda tidak dapat membuat vektor persisten dengan kompleksitas O (1) yang diawetkan untuk mengakses elemen acak.
smossen
2
@smossen dapatkah Anda membuktikannya?
Realz Slaw
1
Pertanyaan pertama Anda adalah pertanyaan yang sangat luas. Ada banyak hasil pada topik struktur data yang dapat dibuat persisten. Orang bisa menulis seluruh buku tentang subjek itu, dan beberapa orang punya: misalnya, buku Okasaki adalah klasik tentang subjek itu. Sudahkah Anda melakukan riset tentang topik ini? Bisakah Anda mempersempit pertanyaan? Seperti berdiri, saya kira itu mungkin terlalu luas untuk menjadi cocok untuk situs ini. Mungkin membagi pertanyaan ke-3 menjadi pertanyaan terpisah?
DW
@Realz Slaw: Saya tidak bisa membuktikannya secara formal, tapi saya pikir itu masuk akal. O (1) akses ke elemen dalam vektor (termasuk tabel hash) tergantung pada waktu yang tetap untuk decoding alamat pada perangkat keras yang diberikan. Kegigihan menambahkan satu atau dua dimensi di samping indeks vektor. Namun alamat perangkat keras masih satu dimensi.
smossen

Jawaban:

22

Hasil positif: kegigihan tidak membutuhkan biaya terlalu banyak. Satu dapat menunjukkan bahwa setiap struktur data dapat dibuat sepenuhnya persisten dengan paling banyak pelambatan .O(lgn)

Bukti: Anda dapat mengambil larik dan membuatnya tetap menggunakan struktur data standar (misalnya, pohon biner seimbang; lihat bagian akhir jawaban ini untuk sedikit lebih detail). Ini menimbulkan perlambatan : setiap akses larik membutuhkan waktu dengan struktur data persisten, alih-alih waktu untuk larik non-persisten. Sekarang ambil algoritma imperatif yang waktu berjalannya dalam model RAM adalah , di mana menunjukkan jumlah memori yang digunakan. Merepresentasikan semua memori sebagai satu array besar (dengan elemen), dan membuatnya persisten menggunakan peta persisten. Setiap langkah dari algoritma imperatif menghasilkan paling banyak pelambatan , sehingga total waktu berjalan adalahO ( lg n ) O ( 1 ) O ( f ( n ) ) n n O ( lg n ) O ( f ( n ) lg n )O(lgn)O(lgn)O(1)O(f(n))nnO(lgn)O(f(n)lgn) .

Tampaknya mungkin untuk melakukan sedikit lebih baik: ternyata seseorang dapat mengurangi faktor perlambatan menjadi (diharapkan, waktu diamortisasi), menggunakan teknik-teknik dalam makalah Demaine yang dikutip di bawah ini - tapi saya tidak terbiasa dengan detail dari pekerjaan itu, jadi saya tidak bisa menjamin ini sendiri. Terima kasih kepada jbapple untuk pengamatan ini.O(lglgn)


Hasil negatif: Anda tidak dapat menghindari perlambatan, untuk beberapa struktur data. Untuk menjawab pertanyaan ketiga Anda, ada struktur data di mana diketahui bahwa membuat mereka kegigihan memperkenalkan beberapa perlambatan.

Secara khusus, pertimbangkan array elemen. Tanpa kegigihan, setiap akses larik membutuhkan waktu (dalam model RAM). Dengan kegigihan, tampaknya telah ditunjukkan bahwa tidak ada cara untuk membangun array persisten dengan kompleksitas kasus terburuk untuk mengakses elemen acak. Secara khusus, tampaknya ada batas bawah yang menunjukkan bahwa array persisten penuh harus memiliki waktu akses . Batas bawah ini dinyatakan pada hal.3 dari makalah berikut:O ( 1 ) O ( 1 ) Ω ( lg lg n )nO(1)O(1)Ω(lglgn)

Batas bawah dikaitkan dengan Mihai Patrascu, tetapi tidak ada kutipan ke sumber yang memberikan rincian bukti dari batas bawah yang ditegaskan ini.


Daerah penelitian yang kaya. Jika kita mengambil struktur atau algoritme data yang arbitrer, ini sedikit pertanyaan yang sulit apakah Anda bisa membuatnya paling lambat melambat atau tidak. Saya tidak tahu ada teorema klasifikasi umum. Namun, ada banyak penelitian tentang cara untuk membuat struktur data spesifik persisten, dengan cara yang efisien.O(1)

Ada juga koneksi yang kuat dengan bahasa pemrograman fungsional. Secara khusus, setiap struktur data yang dapat diimplementasikan dengan cara yang berfungsi murni (tanpa mutasi) sudah merupakan struktur data yang persisten. (Kebalikannya tidak harus demikian, sayangnya.) Jika Anda ingin menyipitkan mata, Anda dapat menganggap ini sebagai semacam teorema klasifikasi parsial yang lemah: jika dapat diterapkan dalam bahasa pemrograman yang berfungsi murni dengan batas waktu yang sama seperti pada bahasa imperatif, maka ada struktur data persisten dengan batas waktu yang sama dengan yang tidak persisten. Saya menyadari ini mungkin bukan yang Anda cari - itu sebagian besar hanya ungkapan ulang sepele dari situasi.


Cara membuat array persisten. Saya tidak akan mencoba menggambarkan konstruksi untuk cara membangun array yang persisten sepenuhnya dengan waktu akses terburuk. Namun, ide dasarnya tidak terlalu rumit, jadi saya akan meringkas inti dari ide tersebut.O(lgn)

Ide dasarnya adalah bahwa kita dapat mengambil struktur data pohon biner, dan membuatnya gigih menggunakan teknik yang disebut path copying . Katakanlah kita memiliki pohon biner, dan kami ingin mengubah nilai dalam beberapa daun . Namun, untuk ketekunan, kami tidak berani mengubah nilai di daun itu di tempat. Sebagai gantinya, kami membuat salinan daun itu, dan mengubah nilai dalam salinan. Kemudian, kami membuat salinan induknya, dan mengubah penunjuk anak yang sesuai di salinan untuk menunjuk ke daun baru. Lanjutkan dengan cara ini, kloning setiap node di jalur dari root ke daun. Jika kita ingin memodifikasi leaf pada kedalaman , ini membutuhkan penyalinan node.d ddd

Jika kita memiliki pohon biner seimbang memiliki node, maka semua daun memiliki kedalaman , jadi operasi ini pada pohon biner membutuhkan waktu. Ada beberapa detail yang saya lewati - untuk mencapai terburuk, kita mungkin perlu menyeimbangkan kembali pohon untuk memastikannya tetap seimbang - tetapi ini memberikan intinya.O ( lg n ) O ( lg n ) O ( lg n )nO(lgn)O(lgn)O(lgn)

Anda dapat menemukan lebih banyak penjelasan, dengan gambar-gambar cantik, di sumber daya berikut:

Itu akan memberi Anda ide utama. Ada detail tambahan yang harus diperhatikan, tetapi detailnya di luar ruang lingkup untuk pertanyaan ini. Untungnya, ini semua hal standar, dan ada banyak informasi yang tersedia dalam literatur tentang cara membangun struktur data tersebut. Jangan ragu untuk mengajukan pertanyaan terpisah jika sumber daya di atas tidak cukup dan Anda ingin informasi lebih lanjut tentang detail membangun struktur data array persisten.

DW
sumber
Saya tidak begitu mengerti paragraf pertama, bagaimana saya membuat array tetap menggunakan pohon merah-hitam?
G. Bach
@ G.Bach, ada penjelasan yang cukup bagus di bagian yang berlabel "Pohon pencarian biner" dan "Struktur akses acak" (khususnya, metode pohon) di toves.org/books/persist/index.html . Untuk deskripsi bagus lainnya, lihat netcode.ru/dotnet/?artID=6592#BinaryTrees dan beberapa bagian selanjutnya. Itu akan memberi Anda ide utama. Detailnya di luar ruang lingkup untuk pertanyaan ini, tetapi ini semua hal standar; Saya mendorong Anda untuk mengajukan pertanyaan terpisah jika Anda ingin informasi lebih lanjut tentang cara membangun struktur data tersebut.
DW
4
O(lglgn)