Güncelleme: Bu birleştirme işleminin yanlışlığıyla ilgili güncelleme için aşağıya bakın
İşte olası bir çözümün çok kaba bir taslağı:
Rastgele dengeli bir B + ağacı türü kullanarak bu soruna bir çözüm bulabilirim. Tepeler gibi, bu ağaçların da benzersiz bir temsili var. İkramlardan farklı olarak, bazı anahtarları birden çok kez saklarlar. Bent ve arkadaşlarının "Önyargılı Arama Ağaçları" ndan bir hile kullanarak, her anahtarı yalnızca göründüğü en yüksek (yani köke en yakın) seviyede saklamanın düzeltilmesi mümkün olabilir.
Sıralı bir benzersiz değerler kümesi için bir ağaç, ilk önce her bir değerin, bir işlemdeki her bir değerin bir öncelikle ilişkilendirilmesine benzer şekilde bir bit akışıyla ilişkilendirilmesiyle oluşturulur. Ağaçtaki her düğüm hem bir anahtar hem de bir bit akışı içerir. Yaprak olmayan düğümler, ek olarak, o düğümden köklenen ağacın yüksekliğini gösteren doğal bir sayı içerir. İç düğümlerde sıfır olmayan herhangi bir çocuk bulunabilir. B + -trees gibi, kökten bir yaprağa kadar kendiliğinden kesişmeyen her yol aynı uzunluktadır.
Her iç düğüm ( (B + - ağaçlarda olduğu gibi), soy yapraklarının en büyük anahtarını k içerir. Her biri ayrıca v köklü ağacın yüksekliğini ve i + 1. bitten itibaren k ile ilişkili bit akışını gösteren doğal bir i numarası içerir . En köklü ağaçtaki her anahtar varsa v onun biraz akışında aynı ilk bit vardır, her çocuğun v yaprak ve i ise 1 . Aksi takdirde, v alt öğeleri , hepsi anahtarlarıyla ilişkili bit akışında aynı i bitine sahip olan iç düğümlerdir .vkbenvki + 1vvben1vben
İlişkili bit akışlarına sahip sıralı bir anahtar listesinden bir ağaç yapmak için, önce anahtarları akışlarındaki ilk bite göre bitişik gruplara toplayın. Bu grupların her biri için, gruptaki en büyük anahtarın anahtar ve bit akışına sahip, ancak akışın ilk bitini kullanarak bir üst öğe oluşturun. Şimdi büyükanne ve büyükbaba oluşturmak için yeni ebeveynler üzerinde aynı gruplama prosedürünü uygulayın. Yalnızca bir düğüm kalana kadar devam edin; bu ağacın köküdür.
Aşağıdaki anahtar listesi ve (bit başlangıcı) bit akışları altındaki ağaç ile temsil edilir. Bit akışı öneklerinde bir '.' herhangi bir bit anlamına gelir. Diğer bir deyişle, anahtarın A için herhangi bir bit akışı, en başta 0 olan herhangi bir bit akışı, başka hiçbir anahtarın bit akışının farklı olmadığı varsayılarak, diğer ağaçlarla aynı ağacı üretir.
A 0...
B 00..
C 10..
D 0...
E 0011
F 1...
G 110.
H 0001
____H____
/ \
E H
| / \
__E__ G H
/ | \ | |
B C E G H
/ \ | / \ / \ |
A B C D E F G H
Belirli bir iç düğümün her alt öğesi, bit akışının ilk yerinde aynı bite sahiptir. Buna ebeveynin "rengi" denir - 0 kırmızı, 1 yeşildir. Çocuğun bit akımının ilk bitine bağlı olarak bir "lezzeti" vardır - 0 kiraz, 1 nane. Yaprakların lezzetleri vardır, ancak renkleri yoktur. Tanım olarak, kiraz düğümü yeşil bir üst öğeye sahip olamaz ve nane düğümü kırmızı bir üst öğeye sahip olamaz.
Bit akımlarının bitleri düzgün dağılımından IID, ebeveynlerinin sayısı PMF varsayarsak düğümleri olan
2 1 - n
ve beklenen değer . Tüm bu olduğundan beklenen ağaç yüksekliği .n21 - n (n+1)/2n≥2≤3( n - 1i - 1)( n + 1 ) / 2n ≥ 2O(lgn)≤ 34nÖ ( lgn )
Eşit yükseklikte iki ağaca katılmak için, önce köklerinin aynı renkte olup olmadığını kontrol edin. Eğer öyleyse, sol kökten en sağdaki çocuğunu ve sağ kökten en soldaki çocuğunu koparın, sonra bu iki ağaca özyineli olarak katılın. Sonuç aynı yükseklikte bir ağaç veya daha uzun bir ağaç olacaktır çünkü ağaçlar aynı tada sahiptir (aşağıya bakınız). İki ağacın tekrar tekrar birleştirilmesinin sonucu, kesilen iki çocukla aynı yüksekliğe sahipse, onu bir kökün orta çocuğu önce sol kökün geri kalan çocukları ve ondan sonra sağ kökün geri kalan çocukları yapın. 1 ile daha uzunsa, çocuklarını bir kökün orta çocukları, ondan önce sol kökün geri kalan çocukları ve ondan sonra sağ kökün kalan çocukları yapın. Köklerin farklı renkleri varsa, aynı lezzete sahip olup olmadıklarını kontrol edin. Yaparlarsa, onlara ilk kökünü seçerek sağ kök anahtar ve bit akışıyla yeni bir ebeveyn verin. Eğer yapmazlarsa, her köke eski kökün anahtar ve bit akışıyla yeni bir ebeveyn verin (her ilk biti elid), sonra bu ağaçlara özyineli olarak katılın.
Bu algoritmada iki özyinelemeli çağrı var. Birincisi, köklerin aynı renge sahip olması, ikincisi ise köklerin farklı renklere ve farklı tatlara sahip olmasıdır. Kökler olasılık ile aynı renge sahiptir . Bu durumda özyinelemeli çağrı her zaman aynı lezzete sahip kökleri görür, bu nedenle ikinci tip özyineleme asla ilkinden sonra gerçekleşmez. Bununla birlikte, birincisi tekrar tekrar meydana gelebilir, ancak her seferinde olasılık , bu nedenle beklenen çalışma süresi hala . İkinci özyinelemeli çağrı olasılıkla gerçekleşir ve sonraki özyinelemeli çağrılar her zaman farklı renklere sahip ağaçlarda yapılır, bu nedenle aynı analiz uygulanır.1 / 2 O ( 1 ) 1 / 41 / 21 / 2O ( 1 )1 / 4
Eşit olmayan yükseklikte iki ağaca katılmak için, önce sağ ağacın sol omurgasını aşağı doğru takip edin, doğru ağacın daha uzun olduğunu varsayalım. (Diğer durum simetriktir.) Eşit yükseklikte iki ağaca ulaşıldığında, aşağıdaki gibi değiştirilmiş eşit yükseklikte iki ağaç için birleştirme işlemini gerçekleştirin: Sonuç aynı yüksekliğe sahipse, sonuç olan bir çocuk olan ağacı değiştirin birleştirme. Sonuç daha uzunsa, kök için bir üst öğe ekleyerek bir kişi tarafından daha uzun hale getirildikten sonra, diğer ağacın kökünün sağındaki ağacın üst öğesine katılın. Ağaç olasılık ile aynı yükseklikte olacaktır , bu nedenle bu cinsinden sona erer .
O ( 1 )1 / 2O ( 1 )
Güncelleme: QuickCheck sayesinde, yukarıdaki birleştirme yönteminin yukarıdaki benzersiz temsil edilen ağaçlarla aynı ağaçları üretmediğini keşfettim. Sorun, yaprakların yakınındaki ebeveyn seçeneklerinin mevcut kardeşlere bağlı olarak değişebilmesidir. Bu değişiklikleri düzeltmek için, birleşimin olmayan yapraklara kadar gitmesi gerekir . İşte QuickCheck'in bulunduğu örnek:O(1)
a 01110
b 110..
c 10...
d 00000
Yapılmış ağacın [a,b]
yüksekliği 2, yapılan ağacın [c,d]
yüksekliği 2 ve yapılan ağacın joinEqual (tree [a,b]) (tree [c,d])
yüksekliği 3'tür. Ancak, yapılan ağacın [a,b,c,d]
yüksekliği 5'tir.
İşte bu hatayı bulmak için kullandığım kod .