Neden std :: stack varsayılan olarak std :: deque kullanıyor?


91

Bir konteynerin yığın içinde kullanılması için gereken tek işlemler şunlardır:

  • geri()
  • Geri itmek()
  • pop_back ()

Neden bunun için varsayılan konteyner bir vektör yerine bir deque?

Yeniden tahsisleri geri ayırma, push_front () işlevinin verimli bir işlem olması için front () öğesinden önce bir öğe tamponu vermez mi? Asla bir yığın bağlamında kullanılmayacakları için bu öğeler boşa gitmiyor mu?

Bir vektör yerine bu şekilde bir süslemenin kullanılması için bir ek yük yoksa, neden öncelikli kuyruk için varsayılan bir vektör de bir deque değil? (öncelikli sıra için front (), push_back () ve pop_back () gerekir - aslında yığınla aynıdır)


Aşağıdaki Cevaplara göre güncellendi:

Deque'in genellikle uygulanma şeklinin, sabit boyutlu dizilerin değişken boyutlu bir dizisi olduğu görülmektedir. Bu, büyümeyi bir vektörden daha hızlı hale getirir (yeniden tahsis etme ve kopyalama gerektirir), bu nedenle, tamamen öğe eklemek ve kaldırmakla ilgili olan bir yığın gibi bir şey için, deque muhtemelen daha iyi bir seçimdir.

Her kaldırma ve ekleme, pop_heap () veya push_heap () komutunu çalıştırmanızı gerektirdiğinden, öncelikli kuyruğa büyük ölçüde indeksleme gerekir. Bu muhtemelen vektörü orada daha iyi bir seçim yapar, çünkü bir eleman eklemek yine de sabit olarak amorti edilir.


1
'Güncellemenizdeki' mantık pek doğru değil. vektör normal olarak öğeleri sonuna bir deque'den daha hızlı ekler ve kaldırır . deque, öğeleri zorlamak için değil, belleği büyütmek için daha hızlıdır .
Mooing Duck

Yanıtlar:


75

Kap büyüdükçe, bir vektör için yeniden tahsis, tüm öğelerin yeni bellek bloğuna kopyalanmasını gerektirir. Bir dekonun büyütülmesi yeni bir blok tahsis eder ve onu bloklar listesine bağlar - kopyaya gerek yoktur.

Elbette isterseniz farklı bir destek kabının kullanılmasını da belirtebilirsiniz. Öyleyse, fazla büyümeyeceğini bildiğiniz bir yığına sahipseniz, tercihiniz buysa, dekupaj yerine vektör kullanmasını söyleyin.


1
Ancak blok işaretçilerinin listesi büyüdüğünde, bu liste zaman zaman bir vektörün olması gerektiği gibi yeniden tahsis edilmelidir; asimptotik olarak, verimlilikteki herhangi bir kazanç, en iyi durumda sabit bir faktörle olur. Ve yineleyici manipülasyon itme yapmak ve çok daha fazlası için karmaşıktır doğru pop gerekli std::dequebunun için olandan std::vectorve bu işlemler reallocations çok daha sık kullanılacak muhtemeldir. Bunun pratikte std::dequeyeneceğine inanmakta zorlanıyorum std::vector.
Marc van Leeuwen

@Michael Burr: O zaman neden kullanmıyorsun list, neden deque?
bappak

@MarcvanLeeuwen inanmakta zorlandığınızı söylerken ... net bir bakış açısı verebilir misiniz lütfen? Şimdi pratikte std::dequeyenme şansınız olduğuna mı inandığınızı mı std::vector, yoksa hala bundan şüphe ettiğiniz anlamına mı geliyor? Teşekkürler.
aafulei

@fleix Pratik uygulamalarda std::dequeolduğu kadar işe yarayacağına şahsen daha kolay inanmak için neden bu kadar önemli olduğunu anlamıyorum std::vector. Ancak kişisel deneyimim, büyük ve karmaşıklık açısından çok önemli bir görev için değil, kodumun içine serpilmiş birçok küçük durum için yığın ve kuyruk veri yapılarına ihtiyacım var. Bu nedenle küçüklerdeki davranışları büyük olandan daha çok önemsiyorum; ve deque orada özellikle donuk parlıyor. Benim tercihim ikisini de değil, bunun yerine (kendi kendine uygulanmış) tek başına bağlantılı listeleri kullanmaktır. Ancak kilometreniz değişebilir.
Marc van Leeuwen

12

Vektör ve deque'in göreceli değerleri için Herb Sutter'ın Hafta 54'ün Gurusu'na bakın.

Öncelikli sıra ile sıra arasındaki tutarsızlığın, onları farklı insanların uyguladıklarını hayal ediyorum.


2
öncelik_ Sırası gerçekte push / pop_front'u kullanmaz ve birincinin yanı sıra öğelere yapılan başvurular, yığın işlemleri tarafından geçersiz kılınır. Bu nedenle, normal kuyruk durumunun aksine, deque'in hiçbir faydası geçerli olmaz.
Potatoswatter

9
Ayrıca, priority_queuesıralı olarak kalmalıdır, bu nedenle rastgele erişimin daha yüksek ek yükü deque::iteratordaha sorunludur.
Potatoswatter

1
@Potatoswatter: korunan priority_queuebir "sihirli sıraya" sahiptir, sıralanmamıştır. Ancak, amacınız geçerli.
Mooing Duck
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.