Bir yığın ve BST arasındaki fark nedir?
Ne zaman yığın ve ne zaman BST kullanılır?
Elemanları sıralı bir şekilde almak istiyorsanız, BST yığın üzerinden daha mı iyi?
Bir yığın ve BST arasındaki fark nedir?
Ne zaman yığın ve ne zaman BST kullanılır?
Elemanları sıralı bir şekilde almak istiyorsanız, BST yığın üzerinden daha mı iyi?
Yanıtlar:
özet
Type BST (*) Heap
Insert average log(n) 1
Insert worst log(n) log(n) or n (***)
Find any worst log(n) n
Find max worst 1 (**) 1
Create worst n log(n) n
Delete worst log(n) log(n)
Bu tablodaki tüm ortalama süreler, Ekle dışındaki en kötü zamanlarla aynıdır.
*
: bu cevabın her yerinde, BST == Dengeli BST, dengesiz asimptotik olarak berbat**
: bu cevapta açıklanan önemsiz bir değişiklik kullanarak***
: log(n)
işaretçi ağacı yığını n
için, dinamik dizi yığını içinİkili yığının bir BST'ye göre avantajları
ikili bir yığın içine ortalama süre ekleme O(1)
, BST içindir O(log(n))
. Bu , yığınların katil özelliğidir.
Fibonacci YığınıO(1)
gibi amortismana tabi tutulan (daha güçlü) ve hatta Brodal kuyruğu gibi en kötü durumdaki diğer yığınlar da vardır , ancak asimptotik olmayan performans nedeniyle pratik olmayabilirler: Fibonacci yığınları veya Brodal kuyrukları pratikte herhangi bir yerde kullanılıyor mu?
ikili yığınlar, dinamik dizilerin veya işaretçi tabanlı ağaçların, BST yalnızca işaretçi tabanlı ağaçların üzerine verimli bir şekilde uygulanabilir . Öyleyse, ara sıra yeniden boyutlandırma gecikmelerini karşılayabiliyorsak, yığın için daha fazla alan verimli dizi uygulaması seçebiliriz.
ikili yığın oluşturma olduğu O(n)
kötü durum , O(n log(n))
BST için.
İkili yığın yerine BST'nin avantajı
rasgele elemanlar aramaktır O(log(n))
. Bu BST'lerin öldürücü özelliğidir.
Öbek için, O(n)
genel olarak, en büyük eleman hariç O(1)
.
Yığın BST'ye göre "yanlış" avantajı
yığın O(1)
max, BST bulmaktır O(log(n))
.
Bu yaygın bir yanlış anlamadır, çünkü en büyük öğeyi takip etmek için bir BST'yi değiştirmek ve bu öğe her değiştiğinde onu güncellemek önemsizdir: daha büyük bir takas takıldığında, kaldırıldığında ikinci en büyük parçayı bulun. Yığın işlemini simüle etmek için ikili arama ağacını kullanabilir miyiz? ( Yeo tarafından belirtilmiştir ).
Aslında, bu BST'lere kıyasla yığınların bir sınırlamasıdır : tek etkili arama en büyük eleman için olanıdır .
Ortalama ikili yığın eki O(1)
Kaynaklar:
Sezgisel argüman:
İkili bir yığında, belirli bir dizindeki değerin artırılması da O(1)
aynı nedenden kaynaklanır. Ancak bunu yapmak istiyorsanız, yığın işlemlerinde ek bir dizini güncel tutmak isteyeceksiniz. Min yığın tabanlı Öncelik Kuyruğu için O (logn) azaltma tuşu işlemi nasıl uygulanır? örneğin Dijkstra için. Ekstra zaman ücreti olmadan mümkün.
GCC C ++ standart kütüphane gerçek donanıma kıyaslama
Ekleme süreleri hakkında doğru olup olmadığını görmek için C ++ std::set
( Kırmızı-siyah ağaç BST ) ve std::priority_queue
( dinamik dizi yığını ) eki karşılaştırdı ve ben ne var:
Çok açıkça:
yığın ekleme süresi temel olarak sabittir.
Dinamik dizi yeniden boyutlandırma noktalarını açıkça görebiliriz. Sistem gürültüsünün üstündeki her şeyi görebilmek için her 10k insertin ortalamasını aldığımızdan , bu pikler aslında gösterilenden yaklaşık 10k kat daha büyüktür!
Yakınlaştırılmış grafik temelde yalnızca dizi yeniden boyutlandırma noktalarını hariç tutar ve neredeyse tüm eklerin 25 nanosaniyenin altına düştüğünü gösterir.
BST logaritmiktir. Tüm ekler ortalama yığın ekinden çok daha yavaştır.
BST vs hashmap detaylı analiz: hangi veri yapısı içinde std :: harita C ++?
GCC C ++ standart kitaplığı gem5 üzerinde karşılaştırma ölçütü
gem5 tam bir sistem simülatörüdür ve bu nedenle ile birlikte son derece hassas bir saat sağlar m5 dumpstats
. Bu yüzden, bireysel uçlar için zamanlamaları tahmin etmek için kullanmaya çalıştım.
Yorumlama:
yığın hala sabittir, ancak şimdi birkaç satır olduğunu ve her yüksek çizginin daha seyrek olduğunu daha ayrıntılı olarak görüyoruz.
Bu, daha yüksek ve daha yüksek kesici uçlar için yapılan bellek erişim gecikmelerine karşılık gelmelidir.
TODO BST'yi gerçekten çok logaritmik ve biraz daha sabit görünmediği için yorumlayamıyorum.
Ancak bu daha büyük ayrıntı ile birkaç farklı çizgi de görebiliriz, ancak neyi temsil ettiklerinden emin değilim: Üst alt kısmı eklediğimiz için alt satırın daha ince olmasını bekler miyim?
Bir aarch64 HPI CPU üzerinde bu Buildroot kurulumuyla karşılaştırılmıştır .
BST bir diziye etkin bir şekilde uygulanamaz
Öbek işlemlerinin yalnızca tek bir ağaç dalını yukarı veya aşağı doğru kabarcıklandırması gerekir, bu nedenle O(log(n))
en kötü durum takasları, O(1)
ortalama.
Bir BST'yi dengeli tutmak, başka bir öğe için üst öğeyi değiştirebilen ve tüm dizinin ( O(n)
) etrafında hareket etmesini gerektiren ağaç dönüşleri gerektirir .
Yığınlar bir diziye verimli bir şekilde uygulanabilir
Üst ve alt dizinler, burada gösterildiği gibi geçerli dizinden hesaplanabilir .
BST gibi dengeleme işlemleri yoktur.
Delete min, yukarıdan aşağıya doğru olması gerektiği için en endişe verici işlemdir. Ancak her zaman burada açıklandığı gibi yığının tek bir dalını "süzerek" yapılabilir . Öbek her zaman iyi dengelendiğinden, O (log (n)) en kötü duruma neden olur.
Kaldırdığınız her bir tane için tek bir düğüm ekliyorsanız, yığınların silme baskın olacağı şekilde sağladığı asimptotik O (1) ortalama eklentinin avantajını kaybedersiniz ve bir BST de kullanabilirsiniz. Dijkstra, her kaldırma için düğümleri birkaç kez günceller, bu yüzden iyiyiz.
Dinamik dizi yığınları ve işaretçi ağacı yığınları
Yığınlar, işaretçi yığınlarının üstüne etkili bir şekilde uygulanabilir: Etkili işaretçi tabanlı ikili yığın uygulamaları yapmak mümkün müdür?
Dinamik dizi uygulaması daha fazla yer tasarrufu sağlar. Her yığın öğesinin yalnızca aşağıdakilere yönelik bir işaretçi içerdiğini varsayalım struct
:
ağaç uygulaması her öğe için üç işaretçi saklamalıdır: ebeveyn, sol çocuk ve sağ çocuk. Hafıza kullanımı her zaman 4n
(3 ağaç işaretçisi + 1 struct
işaretçi).
Ağaç BST'lerinin ayrıca dengeleme bilgilerine de ihtiyacı olacaktır, örneğin siyah-kırmızılık.
dinamik dizi uygulaması, 2n
iki katına çıktıktan hemen sonra boyutta olabilir . Yani ortalama olarak olacak 1.5n
.
Öte yandan, ağaç yığınının en kötü durum eki vardır, çünkü destek dinamik dizisini boyutunun iki katına çıkarmak kopyalanırken en O(n)
kötü durum alırken, ağaç yığını her düğüm için yeni küçük ayırmalar yapar.
Yine de, destek dizisi ikiye katlanması O(1)
amortismana tabi tutulur, bu yüzden maksimum gecikme dikkate alınır. Burada bahsetti .
Felsefe
BST'ler bir ebeveyn ve tüm torunları arasında (daha küçük bırakılır, daha büyük bırakılır) global bir özellik sağlar.
Bir BST'nin üst düğümü, korumak için küresel bilgi gerektiren orta elementtir (kaç tane daha küçük ve daha büyük element olduğunu bilmek).
Bu global özelliğin bakımı daha pahalıdır (giriş ve ekleme), ancak daha güçlü aramalar (giriş ve arama) sağlar.
Yığınlar, ebeveyn ve doğrudan çocuklar (ebeveyn> çocuklar) arasında yerel bir mülkü korur.
Bir yığının üst düğümü, yalnızca yerel bilgi sağlamak (ebeveyninizi tanımak) gerektiren büyük öğedir.
Karşılaştırma BST ile Heap ile Hashmap:
BST: ya makul olabilir:
yığın: sadece bir ayıklama makinesidir. Etkin bir sırasız küme olamaz, çünkü sadece en küçük / en büyük elemanı hızlı bir şekilde kontrol edebilirsiniz.
karma harita: sadece sıralanmamış bir set olabilir, verimli bir sıralama makinesi değil, çünkü karma herhangi bir siparişi karıştırır.
Çift bağlantılı liste
İki kat bağlantılı bir liste, ilk öğenin en büyük önceliğe sahip olduğu yığının alt kümesi olarak görülebilir, bu yüzden burada da karşılaştıralım:
O(1)
öğelere işaret ettiğimiz için en kötü durum ve güncelleme gerçekten basitO(1)
ortalama, dolayısıyla bağlantılı listeden daha kötü. Daha genel yerleştirme pozisyonuna sahip olma dengesi.O(n)
her ikisi içinBunun için bir kullanım durumu, yığının anahtarı geçerli zaman damgası olduğundadır: bu durumda, yeni girişler her zaman listenin başına gider. Böylece tam zaman damgasını tamamen unutabilir ve listedeki konumu öncelik olarak tutabiliriz.
Bu, bir LRU önbelleği uygulamak için kullanılabilir . Tıpkı Dijkstra gibi yığın uygulamaları için , hızlı güncellemek için hangi düğüm bulmak için, listenin gelen düğüme anahtarından ek hashmap tutmak isteyecektir.
Farklı Dengeli BST'nin karşılaştırılması
Her ne kadar şimdiye kadar gördüğüm "Dengeli BST" olarak sınıflandırılan tüm veri yapıları için asimtotik ekleme ve bulma süreleri aynı olsa da, farklı BBST'lerin farklı ödünleşimleri vardır. Henüz tam olarak çalışmadım, ancak bu ödünleşmeleri burada özetlemek iyi olur:
Ayrıca bakınız
CS ile ilgili benzer soru: /cs/27860/whats-the-difference-between-a-binary-search-tree-and-a-binary-heap
Yığın, yalnızca yüksek düzeylerdeki öğelerin düşük düzeylerdeki öğelere göre daha büyük (maks. Yığın için) veya daha küçük (min-yığın için) olduğunu garanti ederken, BST düzeni ("soldan" sağa ") garanti eder. Sıralanmış öğeler istiyorsanız, BST ile devam edin.
[1, 5, 9, 7, 15, 10, 11]
Geçerli bir dakika-öbek temsil eder, ama 7
, 3. seviyede daha küçüktür 9
, örneğin, bkz görselleştirme için seviye 2. 25
ve 19
elemanları yığınları örnek Ara görüntü . (Öğeler arasındaki eşitsizlik ilişkilerinin katı olmadığını unutmayın, çünkü öğeler mutlaka benzersiz değildir.)
Ne zaman yığın ve ne zaman BST kullanılır
O(1)
BST tüm buluntularda ( O(logN)
) iyidir, yığın findMin / findMax ( ) 'de daha iyidir . Ekleme O(logN)
her iki yapı için. Yalnızca findMin / findMax (örneğin, öncelikle ilgili) ile ilgileniyorsanız öbekle devam edin. Her şeyin sıralanmasını istiyorsanız, BST ile gidin.
Buradan ilk birkaç slayt olayları çok açık bir şekilde açıklıyor.
Başkaları tarafından belirtildiği gibi, Heap aynı veri yapısında yapamaz findMin
veya findMax
O (1) 'de yapabilir. Ancak Heap'in findMin / findMax içinde daha iyi olduğunu kabul etmiyorum. Aslında, ufak bir değişiklikle, TSİ yapabilir hem findMin
ve findMax
O (1) 'de.
Bu değiştirilmiş BST'de, veri yapısını potansiyel olarak değiştirebilecek bir işlem yaptığınızda min düğümü ve maks düğümü izlersiniz. Örneğin, ekleme işleminde min değerinin yeni eklenen değerden daha büyük olup olmadığını kontrol edebilir, ardından yeni eklenen düğüme min değerini atayabilirsiniz. Aynı teknik maksimum değere uygulanabilir. Bu nedenle, bu BST, O (1) 'de alabileceğiniz bu bilgileri içerir. (ikili yığın ile aynı)
Bu BST'de (Dengeli BST), siz pop min
veya pop max
atanacak bir sonraki min değeri min düğümünün halefi olurken, atanacak bir sonraki maksimum değer maksimum düğümün öncüsüdür . Böylece O (1) 'de performans gösterir. Bununla birlikte, ağacı yeniden dengelememiz gerekir, bu yüzden hala O (log n) çalışacaktır. (ikili yığın ile aynı)
Aşağıdaki yorumda düşüncelerinizi duymak isterim. Teşekkürler :)
Benzer soruya çapraz referans Yığın işlemini simüle etmek için ikili arama ağacını kullanabilir miyiz? BST kullanarak Heap simülasyonu hakkında daha fazla tartışma için.
popMin
veya popMax
O (1) değildir, ancak O (log n) 'dir, çünkü her silme işlemi için yeniden dengelenmesi gereken Dengeli bir BST olması gerekir. Bu yüzden ikili yığın ile aynı popMin
veya popMax
O (log n) çalıştıran
İkili bir arama ağacı şu tanımı kullanır: her düğüm için, solundaki düğüm daha az değere (anahtar) ve sağındaki düğüm daha büyük bir değere (anahtar) sahiptir.
Yığın olarak, ikili ağacın bir uygulaması olmak aşağıdaki tanımı kullanır:
A ve B düğümler ise, burada B A'nın alt düğümü ise, A'nın değeri (anahtarı) B'nin değerinden (anahtarı) büyük veya bu değere eşit olmalıdır. (A) ≥ tuşu (B ).
http://wiki.answers.com/Q/Difference_between_binary_search_tree_and_heap_tree
Bugün aynı soruya sınavım için koştum ve doğru anladım. gülümsemek ... :)
BST'nin Yığın üzerinde bir başka kullanımı; önemli bir fark nedeniyle:
Bir Yığın Üzerinde BST Kullanımı : Şimdi, Diyelim ki uçuşların iniş süresini saklamak için bir veri yapısı kullandık. İniş sürelerindeki fark 'd'den küçükse, iniş yapmayı planlayamayız. Ve birçok uçuşun bir veri yapısına (BST veya Yığın) iniş planlandığını varsayın.
Şimdi, t'ye inecek başka bir Uçuş planlamak istiyoruz . Dolayısıyla, selefi ve selefi ile t farkını hesaplamamız gerekir (> d olmalıdır). Bu nedenle, bunun için bir BST'ye ihtiyacımız olacak, bu da bunu dengeliyorsa, yani O (logn) ' da hızlı yapar .
düzenlendi:
Sıralama BST Öbek O (n logn) zaman bunu yapabilir iken, sıralı düzende (Inorder kastetmek) öğeleri yazdırmak için O (n) zaman alır. Yığın min öğesini ayıklar ve diziyi yeniden sıralar, bu da sıralama işlemini O (n logn) zamanında yapar.
from unsorted to sorted sequence. O(n) time for inorder traversal of a BST, which gives sorted sequence.
Sıralanmamış diziden BST'ye, BST'den dizi parçasına hakim olan O (n logn) süresinden daha kısa anahtar karşılaştırmasına dayanan bir yöntem bilmiyorum. (Oysa O (n) yığın yapısı vardır.). Ben yığınlar sıralanmamışlık ve BST sıralanmış yakın devlet belirtmek için adil (anlamsız ise) düşünün.
Yığın, yalnızca daha yüksek düzeylerdeki öğelerin daha düşük düzeylerdeki öğelere göre daha büyük (maks. Yığın için) veya daha küçük (min-yığın için) olduğunu garanti eder.
Yukarıdaki cevabı seviyorum ve yorumumu ihtiyacım ve kullanımım için daha spesifik hale getirmeyi seviyorum. N konum listesi her noktadan belirli bir noktaya (0,0) demek mesafe bulmak ve daha sonra daha küçük bir mesafeye sahip am yerleri dönmek zorunda kaldı. Yığın olan Öncelik Kuyruğunu kullandım. Mesafeleri bulmak ve öbek koymak için her ekleme n (log (n)) n-yerleri log (n) aldı. Daha sonra m'yi en kısa mesafelerle elde etmek için m (log (n)) m-location log (n) yığın silme işlemlerini aldı.
Bunu BST ile yapmak zorunda kalırsam, beni n (n) en kötü durumda yerleştirme olurdu. (İlk değerin çok daha küçük olduğunu ve diğerlerinin sıralı olarak daha uzun ve daha uzun olduğunu ve ağaç sadece sağ çocuğa veya sol çocuğa yayıldığını varsayalım. Min O (1) zaman alacaktı ama yine dengelemek zorunda kaldım, bu yüzden durumumdan ve yukarıdaki tüm cevaplardan, minimum veya maksimum öncelikli değerlerden sonra olduğunuzda yığın için.