Apakah ada struktur data untuk manipulasi daftar cepat dan permintaan pesanan?

9

Kami memiliki satu set, , dari daftar elemen dari set N = { 1 , 2 , 3 , . . . , n } . Setiap elemen dari N muncul dalam satu daftar di L . Saya mencari struktur data yang dapat melakukan pembaruan berikut:LN={1,2,3,...,n}NL

  1. : menyatukan daftar yang berisi y ke akhir daftar yang berisi xconcat(x,y)yx

  2. : membagi daftar yang berisi x langsung setelah xsplit(x)xx

Itu juga perlu melakukan pertanyaan berikut:

  1. : mengembalikan t r u e jika x dan y ada dalam daftar yang sama dan y datang setelah x (tetapi tidak selalu berbatasan dengan x )follows(x,y)truexyyxx

  2. : mengembalikan elemen pertama dari daftar yang berisi xfirst(x)x

  3. : mengembalikan elemen berikutnya setelah x dalam daftar yang berisi xnext(x)xx

Saya sudah datang dengan struktur data yang melakukan update ini di dan pertanyaan di O ( l g ( n ) ) waktu. Saya sebagian besar tertarik pada apakah sudah ada struktur data yang dapat melakukan ini (mudah-mudahan lebih cepat?).O(lg2(n))O(lg(n))

Motivasi: hutan terarah yang berakar dapat diwakili dengan dua set daftar ini dan memungkinkan perhitungan yang cepat dari jangkauan di hutan tersebut. Saya ingin melihat apa lagi yang dapat mereka gunakan dan jika semua ini sudah diketahui.

bbejot
sumber

Jawaban:

11

Simpan bilangan bulat Anda dalam daftar lewati. Daftar lompatan normal diurutkan berdasarkan kunci, tetapi kami hanya akan menggunakannya sebagai representasi dari urutan. Selain itu, pertahankan array ukuran pointer . Setiap elemen array harus menunjuk ke sebuah simpul dalam daftar lewati. Saya percaya ini mendukung n e x t di O ( 1 ) dan semua operasi lainnya di O ( lg n ) .nnextO(1)O(lgn)

Secara khusus:

  • ing atau s p l i t ting dua lewati daftar membutuhkan O ( lg n ) waktu dan oleh karena itu membatalkan paling banyak O ( lg n ) pointer.concatsplitO(lgn)O(lgn)
  • hanya mengikuti pointer ke depan di tingkat daun, mengambil O ( 1 ) waktu.nextO(1)
  • membutuhkan O ( lg n ) waktu: ikuti petunjuk sampai Anda macet, kemudian ikuti pointer kiri. Saat Anda tidak dapat mengikuti petunjuk kiri lagi, Anda berada di penunjuk utama daftar lompatan Anda. Ikuti pointer ke daun, lalu satu pointer maju. Ini adalah elemen pertama dalam daftar.firstO(lgn)
  • agak rumit. Lanjutkan seperti di f i r s t untuk y , tetapi merekam daftar nilai-nilai mana Anda terjebak (yaitu, di mana Anda tidak bisa menindaklanjuti pointer lagi). Kami akan menyebut daftar ini yang Anda rekam "jejak". Lakukan hal yang sama untuk x , tetapi ikuti pointer kanan ketika Anda macet, bukan ke kiri. Jika x mendahului y , jejaknya akan bersilangan. Jejak berukuran O ( lg n ) . Jika setiap elemen dalam jejak dianotasi dengan level yang macet, kita dapat memeriksa persimpangan di waktu O (followsfirstyxxyO(lgn) .O(lgn)

adalah kasus terburuk O ( 1 ) , yang lainnya adalah O ( lg n ) dengan probabilitas tinggi. Mereka dapat dibuat terburuk dengan menggunakan daftar lompatan deterministik.nextO(1)O(lgn)

Saya pikir dapat dibuat O ( lg lg n ) dengan menggunakan pohon-level-linked (2,5) pohon dan meningkatkan duri. Untuk trik bootstrap, lihat " Representasi fungsional murni dari daftar yang diurutkan yang dapat ditutup " oleh Kaplan dan Tarjan.concatO(lglgn)

jbapple
sumber
keren. saya sedang berpikir tentang melewati daftar tetapi tidak bisa melihat bagaimana mengikuti tanpa nilai kunci yang terkait.
Sasho Nikolov
Ini bagus; Saya melihat bagaimana membuat semua update deterministik , yang baik. Saya harus terus membaca untuk memahami O (lg lg (n)). Terima kasih untuk kiriman @jbapple. O(lg(n))
bbejot
1

Masalah leluhur yang paling umum dapat digunakan untuk memecahkan masalah jangkauan pada pohon berakar dinamis, jadi saya bayangkan Anda juga akan tertarik pada yang berikut: Algoritma Optimal untuk Menemukan Leluhur Umum Terdekat di Pohon Dinamis , oleh Alstrup dan Thorup. Makalah ini memberikan batas waktu untuk n tautan dan m nca kueri pada mesin penunjuk. O(n+mloglogn)nm

Shaun Harker
sumber
O(lglg(n))