Menyortir menggunakan tumpukan read-only

14

Pertimbangkan pengaturan berikut:

  • kami diberi tumpukan s yang berisi item.n
  • kita dapat menggunakan jumlah tumpukan ekstra konstan .HAI(1)
  • kita dapat menerapkan operasi berikut pada tumpukan ini:
    1. periksa apakah tumpukan kosong,
    2. membandingkan item teratas dari dua tumpukan,
    3. hapus item teratas dalam tumpukan,
    4. cetak item teratas dalam tumpukan,
    5. salin item teratas dari tumpukan ke tumpukan lain,
    6. salin konten dari satu tumpukan ke tumpukan lain.

Perhatikan bahwa ini adalah satu-satunya operasi yang diizinkan. Kami tidak dapat menukar item dan kami tidak diizinkan untuk mendorong item apa pun ke tumpukan mana pun dengan pengecualian menyalin item teratas ke dalam tumpukan (setelah itu konten tumpukan target sebelumnya dibuang dan hanya akan berisi item yang disalin) .

Berikut ini adalah algoritma untuk mengurutkan tumpukan dengan perbandingan HAI(n2) :

last := empty
for i from 1 to n
  min := empty
  w := s
  while w is not empty
    if w.top > last and w.top < min
      min := w.top
    delete w.top
  print min
  last := min

Bisakah kita berbuat lebih baik?

Apakah ada program yang mencetak daftar item yang diurutkan di tumpukan menggunakan hanya perbandingan ?HAI(ncatatann)

Siddharth
sumber
2
Kedengarannya seperti register berperilaku seperti tumpukan? Sepertinya Anda berbicara tentang operasi push dan pop. Apakah itu pertanyaanmu? Bagaimana Anda mengurutkan tumpukan dengan menggunakan beberapa tumpukan dan operasi tumpukan?
AturSams
2
Dengan register Anda dapat: cukup masukkan setiap angka dalam satu register ( O ( n ) ) dan kemudian terapkan algoritma pengurutan yang biasa (nO(n) ). O(nlgn)
Kaveh
1
Apakah Anda ingin menggunakan register ? Kalau tidak, masalahnya akan sepele, seperti dikomentari oleh Kaveh. HAI(1)
Yuval Filmus
1
Sama sama. Saya pikir kita diberi sejumlah tumpukan, bukan hanya satu, saya akan memperbaikinya.
Kaveh
2
@ Akappa, apakah Anda yakin dapat digunakan dalam melihat ini? Kami tidak dapat menyimpan ukuran sewenang-wenang yang lebih besar dari 1. Apakah Anda tidak perlu menyimpan blok yang diurutkan?
Kaveh

Jawaban:

1

Saya pikir saya sekarang dapat menunjukkan batas bawah nontrivial. Idenya adalah untuk mengimplementasikan program semacam itu dengan keluarga program percabangan perbandingan. Asumsi `read-only 'berarti bahwa keluarga kami dari program percabangan menggunakan sedikit, yaitu , ruang. Kemudian kita menerapkan batas bawah S T = Ω ( n 2 ) dibuktikan oleh Borodin et al. di "Pengorbanan Waktu-Ruang untuk Mengurutkan pada Mesin yang tidak sadar." Ini memberi kita aHAI(catatann)ST=Ω(n2) batas bawah untuk saat itu.n2/catatann

Dengan sedikit lebih detail: Kita dapat membuang operasi 5 di atas. Secara longgar, jika kita sudah dapat membandingkan kepala dua daftar dan mencetak kepala daftar, maka tidak perlu bagi kita untuk mengisolasi kepala daftar pada daftar tertentu. Dengan asumsi ini, kita melihat bahwa setiap register di mesin hanya pernah menyimpan substring terakhir dari input.

Misalkan program register kita memiliki baris kode dan register k , X 1k .X1,...,Xk

Perbaiki . Kami membangun program percabangan perbandingan untuk string dengan panjang n sebagai berikut. Buat simpul untuk setiap tupel ( i , d 1 , , d k ) di mana 1 i dan 0 d 1 , , d kn . Idenya adalah, perhitungan dalam mesin register sesuai dengan jalur dalam program percabangan, dan kami berada di simpul ( i , d 1 , ... , dnn(saya,d1,...,dk)1saya0d1,...,dkn jika kita berada pada baris i di mesin register dan panjang string yang disimpan dalam X i adalah d i . Sekarang, kita harus mendefinisikan tepi diarahkan dari program percabangan(saya,d1,...,dk)sayaXsayadsaya

Jika baris adalah dari formulirsaya

jika maka goto i 1 goto i 2Xkamu<Xvsaya1saya2

maka untuk semua , simpul ( i , d 1 , ... , d k ) dilabeli dengan membandingkan elemen d u -th dan d v -th input, dan memiliki edge "true" masuk ke ( i 1 , d 1 , , d k ) , dan "false" edge to ( i 2 ,d1,...,dk(saya,d1,...,dk)dkamudv(saya1,d1,...,dk) .(saya2,d1,...,dk)

Jika baris adalah dari formulirsaya

, goto line i X1tSebuahsayal(X2)saya

lalu ada panah dari sembarang simpul ke ( i , d 2 - 1 , , d k ) .(saya,d1,...,dk)(saya,d2-1,...,dk)

Jika baris adalah dari formulirsaya

halrsayant(heSebuahd(Xkamu)) , goto line saya

lalu ada panah dari sembarang simpul ke ( i , d 1 , , d k ) yang dilabeli oleh(saya,d1,...,dk)(saya,d1,...,dk) simpul -th input.dkamu

Semoga contoh-contoh ini memperjelas bagaimana saya bermaksud membangun program percabangan saya. Ketika semua dikatakan dan dilakukan, program percabangan ini memiliki paling banyak node, sehingga memiliki ruang O ( log n )nkHAI(catatann)

Siddharth
sumber
0

Apakah Anda dapat menghitung elemen? Lalu, saya pikir, ada implementasi Mergesort yang cukup mudah. Jika Anda dapat menempatkan simbol tambahan pada tumpukan, Anda dapat menyelesaikannya dengan 3 tumpukan seperti ini:

Jika kami hanya memiliki satu elemen, daftar sudah diurutkan. Sekarang asumsikan kita telah mengurutkan bagian atas tumpukan. Kita dapat menyalin bagian atas (dalam urutan terbalik) ke tumpukan kedua dan menempatkan simbol pemisahan di atasnya. Sekarang kita memiliki 3 tumpukan (karena kita dapat mengabaikan simbol yang sudah disortir di bawah simbol pemisahan) dan dapat mengurutkan setengah bagian bawah. Akhirnya kita dapat menyalin bagian bawah yang diurutkan ke tumpukan ketiga dalam urutan terbalik dan menggabungkan kedua bagian kembali ke tumpukan asli.

Semua biaya operasi waktu linear, oleh karena itu kami telah mengurutkan daftar di HAI(ncatatann)

(Perhatikan, bahwa kita membutuhkan tumpukan ukuran ncatatann karena simbol pemisahan, tetapi ini dapat dengan mudah diperbaiki dengan menggunakan tumpukan lain)


Karena Anda tidak dapat meletakkan elemen baru di tumpukan, Anda mungkin mendapatkan masalah di titik pemisahan. Untuk mengatasi ini, Anda dapat melakukan yang berikut dengan beberapa tumpukan tambahan:

Salin bagian atas ke tumpukan tambahan, kemudian lanjutkan dengan elemen yang tersisa seperti sebelumnya. Sekarang Anda tahu persis jumlah elemen yang perlu Anda pertimbangkan dalam setiap langkah dan karenanya tidak memerlukan simbol pemisahan.n-2catatann

catatannccncatatann+cn2catatann2+cn4catatann4+ ...=HAI(ncatatann)HAI(ncatatann)

cero
sumber
Saya tidak yakin saya mengerti. Bagaimana kita, misalnya, menyalin bagian atas tumpukan dengan urutan terbalik ke tumpukan lain ketika kita tidak pernah bisa mendorong elemen apa pun ke tumpukan apa pun?
Siddharth
Kami tidak dapat mendorong elemen baru ke tumpukan, tetapi menurut 5, kami dapat mendorong elemen teratas dari satu tumpukan ke tumpukan lainnya. Jadi menyalin tumpukan dalam urutan terbalik membutuhkan paling banyak waktu linier. Jadi saya kira, bukan itu yang Anda minta?
cero
Anda tidak dapat mendorong apa pun di atas item lain seperti yang dijelaskan dalam pertanyaan.
Kaveh