Bir dizide O (1) push / pop zamanı ile üç yığın uygulanabilir mi?


9

Bir sabit boyutlu dizi kullanılarak iki yığın etkin bir şekilde uygulanabilir: yığın # 1 sol uçtan başlar ve sağa doğru büyür ve yığın # 2 sağ uçtan başlar ve sola doğru büyür. Aynı şey üç istif için de mümkün mü?

Daha spesifik olarak, aşağıdaki koşullar göz önüne alındığında üç istif uygulamak mümkündür:

  1. N nesneyi tutabilen sabit boyutlu bir diziniz var.
  2. Üç yığın boyutunun toplamı <N olduğu sürece, push () başarısız olmamalıdır.
  3. Hem push () hem de pop () işlemleri O (1) zamanını almalıdır.
  4. Diziye ek olarak, yalnızca O (1) ek alan kullanabilirsiniz.

İşte do çözümlerin örnekleridir değil bu gereksinimleri karşılamak:

  • Diziyi 3 sabit parçaya bölme ve her parçayı bir yığın için kullanma (ihlal 2).
  • Yukarıdakine benzer ancak istifler arasında hareketli sınırları vardır (ihlal 3).
  • Basit bağlantılı listeye dayalı uygulamalar (ihlal 4).

Tüm koşulları (1) - (4) tam olarak karşılamasalar bile önemsiz olmayan algoritmaları veya imkansızlık kanıtlarını kabul edeceğim, örneğin, push / pop'un O (1) amortisman süresini aldığı veya ek bellek O (N) 'den daha küçüktür, örneğin O (log N). Veya örneğin, push / pop başına dizinin 5 öğesinden daha az öğesine erişmenin imkansız olduğunu gösteren bir imkansızlık kanıtı.


1
Bu gereksinim 4 ihlali olarak düşünmüyorum bilmiyorum, ama N nesneleri dizinizdeki her "nesne" bir tamsayı dizini gibi ek bir alan içerebilir, o zaman dizi içinde "bağlantılı listeler" uygulayabilirsiniz . 3 dış değişken kullanarak 3 yığının her birinin üst dizinini tutabilirsiniz ve her "nesne" yığındaki önceki öğeye işaret edebilir.
Avi Tal

"Nesneler" derken push () kabul eden ve pop () döndüren şeyleri kastediyorum. Yığın uygulaması açısından, bunlar sadece opak veri yığınlarıdır (örneğin, bir nesne 32 bitlik bir tam sayı olabilir). Yığın uygulaması bu nesneleri hiçbir şekilde değiştirmemelidir.
user1020406

1
Önce bir dizi push işlemi yaptıktan sonra sadece pop işlemleri yaptığınızı düşünün . Sorunun bu sürümü hakkında bilinen bir şey var mı? N-
Dmitri Urbanowicz

Misiniz ilave alan sizi tatmin? Ö(N-)
Dmitri Urbanowicz

Re: "N iter ve sonra N çıkar" sürümü: Bilmiyorum, ama bunu ilginç bir alt problem olarak tanımlamak bile yararlıdır çünkü orada bile bir O (1) çözümünün mümkün olup olmadığı açık değildir. Bkz. @ Alexei'nin cevabı ve üst sınır için yorum dizisi. çözümüne gelince , evet kabul edeceğim. Stackexchange hakkında soru gönderme konusunda yeniyim, bu nedenle zaman içinde daha iyi ve daha iyi çözümlerin sunulduğu vakaları nasıl ele alacağımdan emin değilim. Gördüğüm bir yaklaşım, daha iyi bir şey gönderilmesi durumunda bir cevap kabul etmeden önce bir gün beklemekti, bu yüzden yapacağım. Ö(N-)
user1020406

Yanıtlar:


6

Fredman ve Goldsmith "Three Stacks" da (Journal of Algorithms, 1994) şunu gösterdi: Θ(nε)boşa alan bitleri elde edilebilir. En az 16 kuatuordecillion yottabyte büyüklüğünde diziler için gereken minimum değerdir. Basit bir algoritma israfını tanımladımΘ(n) StackOverflow'daki boşluk kelimeleri bu soruya cevap veriyor . @ Dmitri-urbanowicz yorumlarda belirtildiği gibi, bu temelde sadece dizi olarak muamelen boyut blokları nburada her blok tam olarak bir yığın için kullanılır ve bu yığındaki bir sonraki bloğa tek bir işaretçi içerir.


0

N, temel dizinin uzunluğu olsun. Yığınları büyük parçaların bağlantılı listeleri olarak hayal edebilirim, böylece toplam parça sayısı O'dan (log2 (N)) fazla değildir. Üçüncü yığını ilk ikisi arasına, N / 2 dizinine yerleştirin. Bu yüzden 3 işgal edilmiş alanımız ve 2 ücretsiz alanımız var. Bir yığın sonraki öğeyi kabul edemediğinde, bu bir boş alanın tükendiği anlamına gelir. Diğeri de biterse, tüm bellek biter. Aksi takdirde, N / 2'den büyük olmayan başka bir boş alan vardır. Taşan yığını boş alana devam ettirin. böylece tüm konfigürasyon yığınların ilk yerleşimine benzer. Artık boş bellek, ilkinin yarısından daha fazla olmadığından, bu tür bağlantı işlemlerinin log2 (N) 'den daha fazla olmayacaktır. Her bağlama işlemi, yığının önceki durumunu kaydetmek için sabit miktarda bellek gerektirir. Yani,


1
Büyük parçalardan birinden bir şeyler patlatarak elde edilen hafızayı nasıl geri dönüştürüyorsunuz?
Emil Jeřábek

İyi soru. Hızlı cevap, özgürleşen yığının hafızasını daha önce alındığı boş alana geri döndürmesidir. Peki, o yığın için ayrılan bellek zamanından beri boş alan küçülürse ve yığın şimdi ona bitişik değilse ne olur? Bu, boş belleğin parçalanmasına yol açar, tüm yapımımı bozan 2'den fazla boş alan olabilir.
Alexei Kaigorodov

Haşhaş gerçekten de buradaki problem, ancak Alexei'nin yapısı Dmitri'nin yorumlarda sorduğu sorunun versiyonu için güzel bir üst sınır sağlıyor: ya tüm pop'lardan önce tüm itmelerin gerçekleşmesini istiyorsak? Bu durumda O'dan (log N) daha iyi bir şey olup olmadığını merak ediyorum.
user1020406
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.