MIT Açık Ders malzemeleri

http://ocw.mit.edu

 

6.046J Algoritmalara Giriş, Güz 2005

 

Bu materyallerden alıntı yapmak veya kullanım şartları hakkında bilgi almak için:

 

Erik Demaine ve Charles Leiserson, 6.046J IntroductiontoAlgorithms, Fall 2005. (Massachusetts Institute of Technology: MIT OpenCourseWare). http://ocw.mit.edu (Giriş Tarihi:  08, 01, 2010).                                                      Lisans: Creative CommonsAttribution-Noncommercial-ShareAlike.

Not: Lütfen atıf taparken bilgilere eriştiğiniz gerçek tarihi kullanınız.

Atıflar ve Kullanım Koşulları konusunda daha fazla bilgi için:

http://ocw.mit.edu/terms ve http://www.acikders.org.tr sitesini ziyaret ediniz.

 

DERS 25

 

6.046 kodlu son dersimiz. Bugün burada, önbelleği dikkate almayan algoritmalar hakkında biraz daha konuşmak için bir arada bulunuyoruz. Son derste, hiçbiri fazla zor olmayan,  önbelleği göz ardı eden birkaç algoritma görmüştük. Bugün ise, önbelleği göz ardı eden, ama daha ileri düzeyde, iki tane daha zor algoritma göreceğiz. Heyecan verici bir hava yaratmak için, son dersimizde ileri seviyede bir şeyler yapmayı tasarladım   Daha fazla dağıtmadan, konumuza başlayalım. Son olarak, ikili arama problemini görmüştük.

Daha doğrusu görmedik, ikili aramayı seyrettik. İkili arama, önbelleği dikkate almadığımız durumda iyi netice vermedi. Dersten sonra bazılarınız “ikili aramanın, önbelleği dikkate almayan şeklinin kurulması mümkün değil mi”, diye sordular. Gerçekten, statik arama ağaçları ile bu mümkündür. Bu da gerçekten ikili arama oluyor. Soyut açıdan, bu problemi şu şekilde ifade etmek mümkün: size, önceden sıralanmış N sayıda öğe veriyorum,  bu N öğenin arasında hızlı arama yapabilmeniz için, belli bir statik veri yapısı oluşturuyorum.

Çabuk olmanın, B tabanında log (N) olduğunu ileri sürüyorum. B ağaçları ile hedefimizin, B tabanında log (N)  elde etmek olduğunu biliyoruz. B’ yi bildiğimizde, B ağaçları ile bunu başarabileceğimizi de biliyoruz. Şimdi aynı şeyi, B’yi bilmeden de yapmak istiyoruz. İşte önbelleği dikkate almayan statik arama ağaçları bunu başarıyor. Özetle, yapacağımız şu: tahmin ettiğiniz gibi bir ağaç kullanacağız. Yani N elemanımızı, bir ikili ağacın bütününe depolayacağız. B’yi bilmediğimiz için, B ağaçlarını kullanamayız. Böylece onun yerine ikili ağaç kullanacağız. Buradaki anahtar nokta, ikili bir ağacı nasıl düzenleyeceğimiz.  İkili ağacın N sayıda düğümü olacak Ya da, verileri yaprakların içine de koyabilirsiniz. Fark etmez. 

İşte ağacımız burada. N düğümü var. Ve bunları depoluyoruz, fark ettiğiniz gibi sırasıyla dememişim, normalde bir ikili ağaçta, sırayla depolanırlarsa o ağaç ikili bir arama ağacı olur. Şimdi, bu şeyin içinde bir arama yapacaktık. Arama kökte başlayacak ve bir kök -yaprak yolundan devam edecek. Böylece her şey düzen içinde olduğundan, her noktada sağa mı, sola mı gideceğinizi biliyorsunuz. Yani başka bir deyimle, anahtarların sıralı evrenine sahip olduğumuzu varsayıyoruz.

Öyleyse kolay.  Log N zaman süreceğini biliyoruz. Soru, ne kadar  bellek transferi gerekeceği..  Çok sayıda düğümün, köke ve birbirlerine yakın olmalarını ve bir de blok bulunmasını istiyoruz.  Fakat bu bloğun boyutunun ne olduğunu bilmiyoruz. Yapacağımız, ağacı orta düzeyinde oymak. Ağaç yerleşim planında ve düğümleri bellekte düzenlemede ‘böl-ve-fethet’ i kullanacağız. ‘ Böl-ve-fethet’, ortadan keserek ikiye bölmek esasına dayanıyor ki, biraz acayip.

Bildiğimiz klasik  ‘böl-ve-fethet’  değil. Olmadığını bugün birkaç kere göreceğiz. Böylece, orta düzeyde kestiğiniz zaman, eğer en başlangıçtaki ağacınızın yüksekliği,  log N, belki de kabaca log N artı bir veya bu ölçeklerde ise, yaklaşık olarak log N ‘dir, bu takdirde  ağacın yukarı yarısı, log N bölü iki olacaktır. Aynı şekilde, alt yarımın yüksekliği de, log N bölü iki demektir. Üst ağaçta kaç tane düğüm var?  N bölü iki mi ?  Pek değil. İki üzeri log N/2, N’nin karekökü. Demek ki, burada karekök N düğüm var. Bu nedenle  burada altta da, her yaprak veya bir çift yaprak için,  karekök N tane alt ağaç olacak.

Yani, karekök N tane bu alt ağaçlardan var ve bunlar yaklaşık olarak karekök N sayıda.  Pekiyi  bu şekilde oyuyoruz. Şimdi, her bir parça üzerinde özyineleme yapacağız. Bunun bazı yerlerini yeniden çizmek istiyorum; af edersiniz, sadece biraz daha belirgin kılmak için. Bu üçgenler, gerçek ağaçlar ve kenarlardan hepsi bu yukarıdaki ağaca bağlılar. Böylece asıl yaptığımız ağacın içinde kenarların orta düzeyini oymaktan ibaret. Ve eğer N, ikinin tam bir kuvveti değil ise, taban veya tavanı alarak bulunduğunuz düzeyi yuvarlamalısınız. Ancak, kenarların kabaca orta düzeyinde kesiyorsunuz. Burada pek çok kenar var. Burasını, planınıza göre kesiyorsunuz. Bu size, her biri yaklaşık olarak karekök N boyutunda olan, bir tane üst ve birkaç tane alt-ağaç veriyor.

Pekala, bundan sonra her biri karekök N artı 1 boyutunda olan bu alt-ağaçları, özyinelemeli şekilde düzenliyor, sonra da ardı ardına birbirine bağlıyoruz. Bu özyinelemeli yerleşim düzeni fikridir. Son derste matrislerde özyinelemeli düzeni araştırmıştık. Burada aynı şeyi bir ağaç için yapıyoruz. Böylece, önce ağacın en üst kısmını özyinelemeli olarak düzenlemek istiyorum. İşte üst ağaç ve bunun doğrusal bir dizilim içine özyinelemeli olarak sıkıştırılmış olduğunu hayal ediyorum. Sonra, aynı şeyi ağacın alt kısmındaki parçaların her biri için yapıyorum. İşte, alttaki ağaçlar. Bunların herbirini belli bir doğrusal düzenin içine sıkıştırdım. Ve sonra bu doğrusal düzenleri ardı ardına bağlıyorum. Bu ağacın doğrusal düzeni budur.

Ve bir taban durumuna ihtiyacınız var. Tek bir düğümden oluşan bu taban durumu, tek düğüm düzeyinin olduğu yerde depolu. Pekala, bu özyinelemeli bir ikili arama ağacının yerleşim düzenidir . Bu gerçekten iyi çalışır. Bu düzenimin ne olduğunu tamamen anlaşılır kılmak için, şimdi hemen küçük bir örnek yapalım, çünkü ilk defa görüyorsanız biraz alışılmışın dışındadır. Her zamanki favori resmimi çizeyim.

Şimdi, burada, ne şekilde saydığınıza bağlı, dört veya üç yüksekliğinde bir ağaç var. Orta seviyesinden ikiye bölüyoruz, tamam, işte buna üst ağaç diyoruz.Bunlar da alt-ağaçlar. Böylece, dört tane alt-ağaç var. Yani, ağacın kökünden sarkan dört çocuk var. Bu örnekte her biri aynı boyutta. Hepsinin aşağı yukarı aynı boyutta olmaları gerekir. Burada önce orta seviyede ikiye böldüğümüz en yukarıdaki parçayı düzenliyoruz. Pekiyi önce bu geliyor. Ve sonra alttaki alt-ağaçlar, iki ve üç. Böylece bir dizilimde depolanmış düğümlerin düzenini yazıyorum. Ve sonra bu ağacı ziyaret ediyoruz, böylece dört, beş, altıyı elde ediyoruz. Sonra bunu ziyaret ediyoruz ve böylece yedi,sekiz, dokuzu elde ediyoruz.

Ondan sonra bu alt-ağaç 10,11,12 ve sonra da en sondaki alt-ağaç. Bu15 düğümü içinde depolayacağınız düzene karşılık geliyor. Ve bunu özyinelemeli olarak kurabilirsiniz. Böylece, gördüğünüz gibi yapı oldukça basit; bildiğimiz ve sevdiğimiz bir ikili yapı ama öğeler bu komik biçimde depolanmış. Bu, derinliğine arama düzeni veya düzey düzeni değil; pek çok şey deneyebilirsiniz, ama önbelleği dikkate almadığınız takdirde bunların hiçbirisi çalışmaz.

Bu, çalışan tek yoldur. Aynı husus sezgi için de geçerli, aslında sezgiyle her çeşit B ağacını taklide çalışıyoruz. Yani eğer ikili ağaç isterseniz orijinal ağaç budur. Elinizdeki şeyleri nasıl depolayacağınızın önemi yok. Dallanma faktörü dört olan bir ağaç isterseniz, işte burada. Bu bloklar size dallanma faktörü dördü verir. Aşağıda daha fazla yaprağımız olsa idi, o düğümden sarkan dört çocuk daha olurdu. Bunların hepsi bellek içinde birbiri peşine gruplanmış durumdalar. Ve blok boyutunuz üç olursa, bu yapı blok boyutu üç için  eldeki şeyleri depolamak bakımından kusursuz olacaktır.

Eğer blok boyutunuz 7, yada daha fazla,15 olursa -- eğer sağdaki sayıları sayarsak buradaki  düğümlerin sayısı 15-- eğer blok boyutunuz 15 olursa bu özyineleme,15 cinsinden size mükemmel bir bloklama olanağı verecektir. Genelde olay, aslında , bloğu taklitten ibaret. İkinin ikinci kuvvetinin kuvveti gibi düşünün. Tamam, bu sezgiydi.  Daha açık kılmak için size resmi çözümlemeyi vereyim. Özetle, B tabanında log (N) düzeyinde bellek transferi olduğunu iddia ediyoruz. B’nin herhangi bir değerinde bu iddianın doğru olduğunu ispatlamak istiyoruz. Şimdi yapacağımız şu.  Böl-ve-fethet algoritmasını en son çözümlediğimizde, özyinelemeyi yazmıştık ve taban durumu işin anahtarıydı.

Gerçekten, burada da, belli bir anlamda, taban durumu üzerinde düşüneceğiz. Aslında, algoritmamızda özyineleme yok. Algoritma, belli bir kök-yaprak yolu  üzerinde zaten çözülüyor. Sadece, yerleşimin tanımında bir yinelememiz var. O halde, biraz daha esnek olabiliriz. Yinelemeye bakmamız gerekmiyor. Sadece taban şıkkı üzerinde düşüneceğiz. Büyük üçgenle başladığınızı hayal etmenizi istiyorum. Ortadan kesiyor, daha küçük üçgenler elde ediyorsunuz. Özyinelemeli olarak kesmeye devam ettiğiniz noktayı hayal edin.

Şimdi, bu işlemi hayal edin. Büyük üçgenler her defasında,yükseklikleri bağlamında yarıya iniyorlar. Küçüldükçe küçülüyorlar. Bir üçgenin bir bloğa sığdığı noktada, kesme işlemini durdurun ve o andaki duruma bakın. Aslında özyineleme sonuna kadar devam ediyor, ancak analizinde, parçanın bu üçgenlerden birinin içindeki bloklardan birine, daha doğrusu, bloklardan birinin içine sığan bu kutulardan birine sığmış olduğu noktayı düşünelim. İşte bu noktanın bulunduğu düzeyi bir özyineleme düzeyi olarak adlandırıyorum.

Böylece, özyinelemelerin hepsinin birbirlerine paralel şekilde genişlediğini hayal ediyorum. Ağaçları biraz daha detayladık böylece  --  baktığınız ağacın, bu ağaç içinde üçgenler olduğunu ve bunların boyutu B’ye küçük – eşit .. Pekala, şimdi bir resim çizeyim. Şöyle bir resim çizmek istiyorum. Bu resimde düğümler yerine,  küçük üçgenler var ve bu üçgenlerin boyutu en fazla B. Böylece resim, aşağı yukarı bu görünümde birşey. En çok B boyutunda bir küçük üçgenimiz var. Bunun azami B boyutunda alt-ağaçlardan oluşan bazı çocukları yani ardılları var ve aynı boyutta. Bunlar bir parçanın içinde. Ve özyinelemede potansiyel olarak buna benzeyen başka parçalar var.

Tamam, ama her şeyi çizmedim. Daha, B ve  arasındaki boyutta bir miktar alt-ağaç ile, bu boyutta başka karelerin de olması lazım. O nedenle, bu ağacın tamamını, baştan aşağı, daha düzenli hale soktum. Sonra bu düzeylerde, burada, burada bulunan alt-ağaçların her birinin düzen kalitesini arttırdım.   Bu iki özyineleme düzeyinden sonra, her şeyin bir blok’a sığdığı ortaya çıktı. Her şey aynı boyutta olduğu için, belli bir noktada, zorunlu olarak hepsi bir bloka sığacak.Hatta aslında, bir bloktan daha da küçük olabilirler. Ne kadar küçük?

Bunun için, düzeylerin hepsini, aynı noktada kesiyorum ve  bu ağaçlardan birinin yüksekliği, esas itibariyle en fazla log B olduğunda, kesmeyi durduruyorum, çünkü düğümlerin sayısının yaklaşık  B olacakları nokta bu. Öyleyse, yükseklik ne kadar küçük olabilir? Orta seviyede kesmeye devam ediyor ve en fazla log B olduğunda aynı şekilde duruyorum. Log B bölü iki. Öyleyse, en fazla log B, en az da log B’ nin yarısı oluyor. Bu nedenle, düğümlerin sayısı da, burada B’nin karekökü ve B arasında olabilir. O takdirde bu, daha küçük ve bir blokun sabit faktöründen daha az olabilir; önemi olmayan bir iddia. Pekala bu, --B’nin karekökü küçüklüğünde bir şey olduğunu yazmayacağım bile, çünkü çözümlemede bir rolü yok. Bir kaygıdan ibaret ama bir zararı yok, çünkü sınırımız sadece log B yi  içeriyor. B yi içermiyor.

Şimdi yapacağımız şey şu.. Bu üçgenlerin her birinin yüksekliğinin en fazla B, en az da logB’nin yarısı olduğunu biliyoruz. Ve bu sebepten, eğer bir arama yoluna  bakarsanız –yani bu ağaçta bir arama yaparsanız yukarıdan başlayacağız; şimdi diyagramı karışık hale getireceğim.  Bir yol izleyeceğiz, belki buradan aşağı doğru gider şekilde çizmem daha iyi olurdu. Bu üçgenlerin bazılarını ziyaret ediyoruz ama bir kök – düğüm yolunda .. Öyleyse, üçgenlerden kaç tanesini ziyaret edebiliriz? Cevabı ağacın yüksekliği bölü, bu üçgenlerden birinin yüksekliği. Öyleyse bu, en fazla  log N bölü yarım log B.

Bu, N’nin log tabanı B,  dikkatinizi çekerim, ikinin faktörü. Şimdi merak ettiğimiz, bir üçgenin kaç blok işgal ettiği. Bu üçgenlerden bir tanesinin bir bloka sığması lazım. Ama--özyineleme yerleşiminden bunun bellek içinde birbirini takip eden bölgelerden birinde depolandığını biliyoruz. Öyleyse, kaç blok işgal edebilir? Yanıt: İki, çünkü “alignment  yani hizalamadan ötürü, bir blokun sınırından diğerine taşabilir ve bir üst bloğa da sarkabilir. Yani, bir üçgen iki blok işgal edebilir; bunun anlamı, bir üçgen bir bloğa sığar ama hizalamaya bağlı olarak, B boyutunda en fazla iki blok yani iki bellek bloku içinde olabilir. Öyle ise bellek transfer sayısı, başka bir deyimle okuduğumuz blok sayısı, çünkü burada yaptığımız tek şey arama sırasında okuma -- üçgen başına en fazla iki bloktan ibarettir.

Burada bu kadar üçgen var; öyleyse en fazla, B tabanında log( N ); bu da B tabanında log(N )düzeyindedir. Bu 4 sabitini daha karmaşık veri yapılarıyla değiştirme konusunda yazılmış makaleler var. Sanıyorum ikiden biraz daha az bir değere indirebilirsiniz.

Gördüğünüz gibi sabit açısından B ağaçları kadar iyi değil, ama gene de iyi. Bunun iyi yanı, bu veri yapısının tüm B’ler için aynı zamanda çalışması.

Bu çözümleme bütün B için geçerli. Böylece, karşımızda “multi level memory hierarchy  yani çok katmanlı bellek hiyerarşisi var, ama bu sorun değil. Bu veri yapısı hakkında herhangi bir soru var mı? Bu oldukça karmaşık bir örnek, ama daha da karmaşık hale getireceğiz. İyi, soru yok. Bu, anlattıklarımın ya kusursuz derede açık olduğunu, ya biraz güç geldiğini veya ikisinin birlikte olduğu bir durumu gösteriyor. Bundan sonra, hangi konuda konuşmam iyi olur diye kendimle tartıştım. Doğal olarak bahsedeceğim iki konu var, bunların ikisi de karışık. Belleği dikkate almayan ortamdaki ilk sonucum, bu veri yapısını ‘dinamik’ kılmak. Yani, önümüzde bir dinamik B ağacı var; bu belleği dikkate almıyor ve B’ nin her değerinde çalışıyor ve log B tabanında N veriyor,  Araya yerleştir, sil ve ara. Bu ise sadece B tabanında log (N) düzeyinde arama yapar. Bu veri yapısı ilk makalemizde çok zordu, sonradan kolaylaştı.

Artık çok zor değil, ama ileri algoritmalar sınıfında öğretilmesi dahi birkaç ders alıyor. Ben böyle yapmayacağım. Bilmeniz gereken, mevcut olduğu. Ancak onun yerine, şimdi belleği dikkate almayan, sevdiğimiz “sıralama” sorununu inceleyeceğiz. Bu da çok karmaşık, beklediğinizden de fazla. Genelde, doğru yanıtı elde etmek “multithreaded setting” yani çok izlekli ayarlamada olduğundan çok daha güç.

Belki, çok izlekli ayarlamalarda en iyi yanıtı almak da zor bir şey. Ama geçen hafta gördüğümüz versiyonu çok kolaydı. Fakat, önbelleği dikkate almayan sıralamaya geçmeden önce, ön belleği önemseyen çeşidi üzerinde konuşmak istiyorum., Çünkü sınır olarak neyi amaçladığımızı bilmemiz lazım. Bu arada ikaz edeyim, önbelleği dikkate almayan çeşidin çözümlemesinin tamamını yapamayabilirim, Ancak içine neyin girdiği konusunda bir fikir vermek istiyorum . Çünkü çok güzel fikirlerle dolu...

Pekala, nasıl sıralayabilirsiniz? Belleği önemseyen algoritmada herşeyi yapabileceğimizi varsayıyoruz. Anlamı, temelinde B ağaçları var. Bildiğimiz, tek yapı, o. Sahip olduğunuz tek veri yapısının o olduğunu bilerek, N adet sayıyı nasıl sıralarsınız? Doğru, önce B ağacının içine ekleyin, iç sıralı gezinmeyi uygulayın. Sıralamanın bu yolu oldukça uygun. Buna bir B ağacının içine yinelenen araya yerleştirme diyeceğiz. Kırmızı-siyah ağaçlar gibi dengeli ikili arama ağaçları kullandığınız kurulumda, BST sıralamada N log N zaman aldığını; işlem başına sürenin log N olduğunu ve bunun, kıyaslama modelindeki en iyi sıralama algoritması olduğunu biliyoruz.

Öyleyse bu veri yapısı kaç bellek transferi sürüyor? Afedersiniz, bu sıralama algoritması demek istiyorum . Hatırlayacağınız gibi bellek transferlerinin sayısı, N nin bir fonksiyonudur  ve MT(N)’dir, değil mi? Bu kolay. Burada “in order traversal” ı yani iç-sıralı gezinmeyi düşünmeniz  gerekiyor. Bunun için de geriye giderek, B ağaçlarının çözümlemesini hatırlamanız lazım. Bu da fazla zor bir şey değil. Araya yerleştirme ne kadar zaman alır?   N sayıda araya yerleştirme?  N log B tabanında (N) kadar. “Traversal” yani gezinme  ne kadar süre alır? Daha az zaman. Eğer üzerinde düşünürsek, N bölü B bellek transferinden kurtulabilirsiniz, böylece bundan epeyce az olur. Bu, N den daha büyük ve aslında oldukça kötü. N sayıda bellek transferi demek, gelişi güzel erişim yapıyorsunuz, yani her elemanı gelişi güzel bir düzende ziyaret ediyorsunuz demektir. Bu ise daha da kötü. Şimdi log faktörü, bu log B faktörü ile azalıyor. Yani gerçekten kötü bir sıralama sınırı.

Demek ki, sıralama için bir arama ağacını kullanmanın iyi bir yol olduğu normal algoritmaların aksine, önbelleği dikkate almayan veya  önemseyen  sıralamalarda gerçekten çok, çok kötü. Öyle ise sıralamanın ne olduğunu bilerek kullanabileceğiniz normal başka algoritma ne olabilir? Hatta ön belleği dikkate almayanlarda bile -- şimdiye kadar gördüğümüz bütün algoritmalar önbelleği dikkate almıyordu. Öyleyse hangisi denemek için iyi olabilir? Birleştirme sıralaması ? Evet, çokizlekli algoritmaları birleştirme sıralamasında kullanmıştık; şu iyi böl-ve-fethet’ le birleştirme sıralamasını bir deneyelim. Bundan böyle,  ismine ikili birleştirme sıralaması yani “binary merge sort” diyeceğim, çünkü hem dizilimi ikiye bölüyor, hem de her iki parça üzerinde de özyineleme yapıyor. Böylece karşımıza bir ikili özyineleme ağacı çıkıyor. Öyleyse bunu çözümleyelim.. N sayıda eleman üzerinde bellek transfer sayısı: N elemanın oldukça iyi bir özyineleme yerleşimi var, değil mi? Dizilimimizi böldükten sonra elde etmiş olduğumuz iki alt-dizilim,  ardı ardına dizilmiş. Bunun üzerinde ve bunun üzerinde özyineleme yapıyoruz.

Önbelleği dikkate almayan, güzel bir önbelleği dikkate almayan yerleşim. Bu yerleşim önbelleği önemseyen bir algoritma için bile iyi. Bu çok iyi bir algoritma, göreceğimiz gibi, bundan çok daha iyi. Ama elde ettiğimiz yineleme ne? Bunun için, önbelleği dikkate almayan özyinelemeli algoritmaları görürken, özyinelemeler hakkında düşündüğümüz son derse geri dönmemiz gerekiyor. İlk kısım oldukça kolay demek istiyorum. Bir büyük O mu var?. Tamam O ile böl-ve-fethet i en sonA alalım. Özyineleme, N bölü ikinin 2MT si, iyi.

Bu tıpkı birleştirme sıralaması özyinelemesinde olduğu gibi. Düşündüğünüz şey de toplanır terimler. Normal olarak, buraya doğrusal bir toplanır terim ödeyecektik çünkü birleştirme N düzeyinde  zaman alır . Şimdi iki girdi ve bir çıkıştan oluşan üç paralel tarama’yı birleştiriyoruz. Doğru, tam paralel değiller, aralarında serpiştirmeler var. Biraz komik bir şekilde serpiştirilmişler ama, önbelleğiniz en az üç bloku depo ettiği sürece, bu ayarlamada bu da doğrusal zamanlı-- ve her bloğu ziyaretiniz aynı sayıda olur demektir.

Bu, özyineleme. Şimdi, şüphesiz bir de taban durumuna ihtiyacımız var.  İki taban durumu gördük: biri B nin MT si idi, diğeri önbelleğe sığan her ne ise onu ifade eden MT. Şimdi ona bakalım, çünkü o daha iyi. Böylece bir C sabiti için, eğer M boyutunda bir dizilimim var ve önbelleğe sığıyor ise, aslında C burada muhtemelen birdir ama, ben gene de dikkatli olacağım. Belli bir sabit -- bu önbelleğe sığıyor.Bu boyuttaki bir problem önbelleğe sığıyor ve o durumda bellek transfer sayısı  -- kimse hatırlıyor mu?  Bu taban durumunu birden fazla kez kullanmıştık. Hatırlıyor musunuz? 

Afedersiniz? CM bölü B. Burada büyük O var, öyleyse M bölü B. M bölü B düzeyinde, çünkü bu verilerin boyutu. Yani, sadece içindekilerin hepsini okumanız M bölü B alıyor. Bir kere de önbelleğin içinde olduktan sonra, burada doğru sabit için doğrusal mekan kullandığım sürece, ne yaptığım fazla bir önem taşımaz. Başka bir deyimle, o algoritmada doğrusal mekan kullandığım sürece önbelleğin içinde kalacağımdan, en sonuna  kadar hiçbir şeyi dışarı yazmama ihtiyaç olmayacak ve ancak bu sonuncu halde, tamamını yazmak için, M bölü B’yi kullanacağım.

Yani, doğrusal mekan kullandığı sürece, hangi algoritmayı kullandığım önem taşımıyor ve M bölü B’den fazla bir harcama yapmam gerçekten söz konusu olmuyor. Böylece bu aşağı yukarı her algoritmada faydalı bir taban durumu oluşturuyor. Tamam özyineleme bu. Şimdi çözmemiz gerekiyor. Önce, ikili birleştirme sıralamasının ne kadar iyi olduğunu görelim. Bu özyinelemenin ardındaki yanıt için gerekli sezgiyi vereceğim ve ispatı için “substitution” yani yerine koyma metodunu kullanmayacağım. Fakat bu gerçekten oldukça basit. Böylece, en yukarıda – aslında buraya yazacağım, aksi takdirde ben göremeyeceğim. Özyinelemenin en yukarısında, N bölü B maliyeti var diyorduk. Sabitleri dikkate almıyorum. Bir olasılıkla, toplanır sabitler de var. Burada onları da hesaba katmıyorum. Sonra bunu yarı boyutta iki probleme dönüştürüyoruz ve yarım N bölü B ile, yarım N bölü B elde ediyoruz.

Ve aslında bu N, yarım N ve yarım N idi. Bunun eminim birinci dersten hatırlıyorsunuzdur. Böylece bu düzeydeki genel toplam, N bölü B’dir. Bu düzeydeki toplam da N bölü B’dir. Bunun her düzeyde aynı, yani N bölü B olduğunu tümevarım ile kanıtlayabilirsiniz. Soru, kaç düzey olduğudur. En altta -- yani nokta, nokta, nokta, bu özyineleme ağacının en altında, M boyutunda bir şey elde etmemiz lazım ve M  bölü  B öderiz. Aslında burada  M bölü B ödüyoruz.

Sonuçta bunların birbirine uyumlu olması iyi bir şey. Uyumlu olmalılar. Burada yaprak grupları var, tamamının boyutu M bölü B. Buradaki yaprakların sayısını hesaplayabilirsiniz, o da N bölü M. Eğer kesin emin olmak istiyorsanız, yaprakların düzeyini kontrol etmelisiniz. Bu iyi bir fikirdir.  Böylece, N bölü M yaprağımız var, herbirinin maliyeti, M bölü B. Bu bir M. Öyleyse, bu da N bölü B. Yani buradaki her düzey N bölü B bellek transferi yapıyor. Ve düzeylerin sayısı ---  N bölü B mi? Log N bölü B. Evet, doğru. Ben doğru duymamışım. Pekala, N de başlıyoruz. M ye doğru aşağı iniyoruz. Böylece, ikili ağacın tümünü log N olarak düşünebilirsiniz eksi bu alt ağaçlar log M,  bu da log N bölü M ile aynı veya nasıl düşünmek istiyorsanız öyle. 

Burada önemli nokta, bunun log tabanının iki olması. Yani burada çok da başarılı değiliz . Aslında bu oldukça iyi bir algoritma .Bu sebeple yanıtı buraya yazayım. Demek ki,  N eleman üzerinden bellek transfer sayısı, düzeylerin sayısı kere her düzeyin maliyeti ediyor. Bu da, N bölü B çarpı log 2 tabanında (N bölü M), ki bu da bir B ağacında yinelenen araya yerleştirmeden  çok daha iyi. Burada, N çarpı log N bölü log B elde ediyorduk, yani N log N bölü log B oluyordu ki böylece, hiçbir şeye yaramayan bir log B kadar tasarruf ediyorduk. Burada ise bir B faktörü kadar tasarruf elde ediyoruz. N log N bölü B. Gerçekte, bunu N bölü M ile bölerek daha da küçültmüş olduk. Bu çok fark ettirmez. Ama bu B ile bölme, önemli bir şey. 

Pekala, yakında oraya varıyoruz. Bu algoritma en iyiye yakın bir algoritma. Önbelleği dikkate almıyor bile ve bu oldukça iyi. O küçük ek adıma gelince, bir log B faktörü kadar daha geliştirebilmek lazım. Ben bu iki fikri birleştirip, hem N log N’deki bu B faktörü gelişimini korumak istiyorum, hem de  N log N’deki bu log B faktörü gelişimini korumak istiyorum ve bunları birleştirmek istiyorum. Bunun için bu işi önbelleği dikkate almayan biçimde yapmadan önce, önbelleği önemseyen biçimde yapacağız.

Bu önbelleği önemseyen üçüncü algoritma oluyor. Bu önbelleği dikkate almayan bir algoritma idi. Şimdi daha iyi sonuç almak için, bir birleştirme sıralamasını yani merge sort‘u nasıl değiştirmeliyim? Demek istediğim, elimde bu log iki tabanı var, benim istediğim yaklaşık  bir log B tabanı. Bunu birleştirme sıralaması ile nasıl yapabilirim? Evet ? --------   B alt-dizilime bölerek, doğru. Yani, ikili birleştirme sıralaması yapmak yerine, burada ben bunu kastediyordum,--  önce iki parçaya bölüp, bu iki parça üzerinde özyineleme yapıp sonra da onları birleştirmek yerine, onları potansiyel olarak daha fazla parçaya bölebilirim. Bunu yapmak için önbelleğimi kullanacağım. Buradaki fikir,  B- parçaları. Bu parçaların uygun olmalarına karşın, yapılacak en iyi şey bu değil. Daha önce bunu ima ettim, çünkü  bir log B’ye ihtiyacım var diyordum . Aslında benim istediğim tam log B değil; log M bölü B. Sorun değil. Bakalım. Pekiyi o halde, en fazla kaç parçaya  bölebilirim?

bunu N parçaya bölebilirim. Bu iyi olurdu, değil mi?  Hem de sadece tek özyineleme düzeyinde? Ama N parçaya bölemem. Niçin?  N sayıda parçaya bölersem bunun nesi yanlış olur? Çünkü bu en sonu olur. ---- Tam birleştirme yapamazsınız. Yani elimde N parça varsa bunları önbellekte birleştiremem. Demek istediğim, önbellekte birleştirme yapabilmem için, birleştireceğim her listeden oluşan  blokların tamamını  önbellekte depolayabilmem lazım. Eğer her liste için bloğun tamamını önbelleğe depolayabiliyorsam, o takdirde bu bir paralel taramalar demeti olur. Bu da paralel tarama teknolojisinin bir anlamda limitini test etmek gibi bir şey olur. Eğer K paralel taramanız var ise ve K sayıda bloğu önbelleğe sığdırabiliyorsanız, ancak o zaman her şey yolunda demektir, çünkü ancak o zaman hem o K dizilimlerinin her biri içinde tarama yapabilirken, hem de aynı anda K dizilimlerinin her birinden önbellekte bir blok  olabilir. 

İşte, buradaki fikir de bu. Şimdi önbelleğe kaç blok sığdırabilirim? M bölü B. Yapabileceğimin en iyisi bu. Bu da, bu çeşit birleştirme sıralaması algoritmaları arasında en iyi koşma süresini verecektir. Yaptığımız, bir  “ M bölü B tarzı birleştirme sıralaması “. Böylece şimdi,  bir dereceye kadar daha iyi bir özyineleme elde ederiz. Gerçekten de şimdi, M bölü B boyutunda alt-problemler halinde bölüyoruz ve bu parçaların her birinin boyutu, N’nin, M bölü B’ye bölündüğünde çıkan sonuç kadardır. Şimdi iddiamız, birleştirme zamanının hala doğrusal olduğu, çünkü  zaten ancak yetecek kadarına sahibiz.. Belki bu algoritmayı açıklamalıyım. Özetlersem, bölüyoruz çünkü şimdiye kadar ikili olmayan birleştirme sıralamalı bir algoritmayı hiç yapmadık. Bölerek, iki tane yerine,  M bölü B boyutunda, birbirine eşit alt-dizilimler oluşturuyoruz. Burada açıkça  önbelleği önemseyen bir algoritma yapıyoruz; M bölü B nin ne olduğunu bildiğimizi varsayarak..

Sonra özyineleme yapıyoruz;  özyinelemeli olarak her alt-dizilimi sıralıyoruz, --sonra da fethediyoruz; birleştiriyoruz.  Ve birleştirme çalışıyor çünkü önbellekte bir blok ayırabiliyoruz. Buna, ”altdizilim başına bir önbellek bloğu“ diyelim. Aslında dikkat ederseniz, çıkışa göndermeden önce, birleştirilmiş dizilimin çıkışı için de bir bloğa ihtiyacınız var. Öyle ise, bu da M bölü B eksi bir olmalı. Fakat bazı toplanır sabitleri dikkate almayalım. Böylece elde ettiğimiz özyineleme bu olur. Taban şıkkı aynı.

Öyleyse,  burada daha iyi olan ne? Demek istediğim, düzey başına maliyet değişmiyor, en azından ben böyle iddia ediyorum,  çünkü en üstte daha önce de olduğu gibi N bölü B elde ediyoruz. Sonra, M bölü B boyutlu alt-problemleri böldük, her birinin maliyeti de bir bölü M/B faktörü çarpı N bölü B.. Tamam, bunların hepsini topladığınızda ,hala N bölü B elde ediyorsunuz, çünkü elemanların sayısını azaltmıyoruz. Onları, sadece bölüyoruz. Şimdi, M bölü B alt-problem var ve her biri bir bölü M/ B boyutunda..

Böylece, daha önce olduğu gibi, her düzeyin toplamı N bölü B olacak. Değişen sadece düzeylerin sayısı, çünkü şimdi dallanma faktörümüz daha büyük; buradaki log tabanı ikiydi, şimdi log tabanı dallanma faktörü kadar oldu. Öyleyse bu ağacın yüksekliği, sanırım log M bölü B tabanında,  N bölü M oluyor. Bunu bir kontrol edeyim. –Evet.. -- tamam. Eğer dikkat ederseniz bu, düzeylerin sayısını değil, ondan bir eksiğini veriyor. Bu nedenle buraya artı biri ekleyeceğim. Sebebi, istediğim sınırın tam olarak bu olmaması.                       

Şimdi elimizde M bölü B tabanlı bir log var; aslında benim istediğim N bölü B. Bunların her ikisinin de eşit olduklarını iddia ediyorum çünkü burada bir eksi terim daha var. -- tamam, bu iyi. Bu sizlere biraz esrarengiz gelebilir ama ben sıralama sınırının ne olması gerektiğini biliyorum. Biraz aritmetik yapıyorum. N bölü M’nin, log M bölü B tabanındaki değerini alıyorum. Log’un tabanını değiştirmiyorum. Sadece N bölü B’nin,  M bölü B’ye bölünmüş halidir diyorum; çünkü B’ler gidiyor ve M aşağıya iniyor. Öyleyse, bunu log’larda yaparsam, N bölü B’nin logu eksi  M bölü B’nin logu -- eksi çünkü  bölüyorum. Şimdi, M bölü B nin, log M bölü B tabanındaki değeri bir eder.

Öyleyse, bunlar birbirini götürür ve log M bölü B tabanında, N bölü B elde ederim ki   hedeflediğim de buydu. Niçin? Çünkü yazılışı doğru olan sınır bu. Şimdi, önbelleği dikkate almayan yoldan bunu elde etmeye çalışacağız. Demek ki, arama ağacının yüksekliği bu ve her düzeyde N bölü B bellek transferi ödüyoruz. Öyleyse bu M bölü B tarzı birleştirme sıralaması için toplam bellek transfer sayısı, sıralama sınırıdır.

Bunu çerçeveye alacağım. Sıralama sınırı bu oldu, -- çok özeldir, çünkü N öğeyi önbelleğin farkında olan yoldan sıralamak için, en iyi bellek transfer sayısına karşılık gelir. Bu, 1983’ten beri biliniyor. Yapılacak en iyi şey bu. Gerçekten biraz acayip bir sınırdır, ancak B’ lere bölme işlemini dikkate almazsanız, N çarpı , M log M tabanında N gibi bir şey kalıyor.  Bu biraz daha makul.  Ancak, B’ lerle bölünmüş çok şey var. Böylece,  “girdideki blokların sayısı” --- çarpı “önbellekteki blokların sayısı tabanlı” logaritma --, ve log işlemine alınacak “girişteki blokların sayısı” . Bu biraz daha sezgisel. Ama sınır da bu ..

Bizim hedeflediğimiz de bu. Yani bu algoritma sonuna kadar, bizim M bölü B nin ne olduğunu bildiğimizi var sayıyor. Şimdi işlemi, M bölü B’yi bilmediğimizi var sayarak önbelleği dikkate almayan şekilde yapacağız. Bunun sonucuna sadece birkaç yıl önce varılabildi. Hazır mısınız? Buraya kadar her şey açık mı? Çok olağan bir algoritma. Temelde onu taklit edip bir birleştirme sıralaması yapacaktık,  ama bir “M bölü B tarzı birleştirme sıralaması” yapmayacağız, çünkü bunun nasıl yapıldığını bilmiyoruz.

Bir karekök N yöntemli birleştirme sıralaması yanisquare root of N way merge sort” yapmaya çalışacağız. Eğer bununla biraz oynamak isterseniz doğal olanı budur. Buradaki şaşırtıcı taraf, N’nin kare kökü listelerini aynı anda önbellek verimliliği açısından etkin bir şekilde birleştirmenin güçlüğüdür. Biliyoruz ki, eğer N’nin karekökü,  M bölü B den büyükse, doğrudan bir birleştirme yaparsanız, çuvallarsınız. Öyle ise daha gösterişli bir birleştirmeye ihtiyacımız var. Böl-ve-fethet-birleştirmesi yapacağız. Bu, geçen hafta gördüğümüz çok izlekli algoritmalara çok benziyor, --  böl-ve-fethet-birleştirmesini yaptığımızda, ne kadar liste birleşirse birleşsin, bunlar N’nin karekökünden küçük, hatta küp kökünden küçük olduğu sürece, önbellekte bu birleşmeyi etkin şekilde yapabilirsiniz, değil mi?  Öyleyse bunu yapacağız, ancak bir kuruluma ihtiyacımız var, çünkü önbelleği dikkate almayan sıralamayı bu kurulumda yapacağız. Sıralama sınırını elde etmek istiyoruz.

Önbelleği dikkate almayan sıralama yapmak için, önbellek boyutu üzerinde bir varsayım yapmanız gerekir. Bu biraz sıkıcı, çünkü, önbelleği dikkate almayan algoritmanın, hem B’nin, hem de M’ nin tüm değerlerinde çalışması gerektiğini söylemiştik. Aslında bu sınırı önbelleği dikkate almayan yoldan elde etmek için, bir varsayıma daha ihtiyacınız olduğunu kanıtlayabilirsiniz.

Geçen yıl Garret Brodel’ın vardığı sonuç gibi. Varsayım temelde oldukça zayıf. Bu iyi haberdi.  Aslında birkaç kez varsayım yapmıştık; önbellek en az üç blok yada en az dört blok depolayabilirse,-- evet önbelleğin en az dört bloğu veya en az sabit sayıda bloğu depolayabileceğini düşünmek makuldür. Bu, önbelleğinizin depo edebileceği blokların sayısının, en az B’nin Epsilon kuvvetine kadar olduğunu söylüyor.

Bu, önbelleğinizin gerçekten dar olmadığını anlatıyor. Yüksekliği ile eni yaklaşık aynı. Bu da size büyük rahatlık veriyor. Şimdi, M’nin en az  olduğu varsayımının basit bir versiyonunu kullanacağız. Bu çok doğal. Bu, bloklarınızın bulunduğu önbelleğinizin geniş olduğu kadar yüksek olduğunu ifade ediyor.Oldukça makul bir varsayım ve bugünlerdeki önbelleklere bakarsanız, hepsi de belli epsilon boyutlarıyla varsayımımızı karşılıyor..

Genelde, M en az  veya o civarda olur. Geçenlerde konuştuğumuz ışık hızı konusu açısından da,  veya  gerçekten yapılacak doğru şey oluyor. Dışarı, 3-D yani 3 boyuta çıktığınızda, , oradaki mekanın yüzey alanı olur. Demek ki bu, belli bir mesafede ne kadar mekanınız olması gerektiğini göstermesi açısından da doğal. Sabit boyutlu bir alanda yaşadığımızı varsayarsak, bu varsayım doğru çıkacak. Bu boyutların 42 ya da daha fazla olması halinde bile geçerlidir. Yani oldukça makul bir yaklaşımdır. Pekala, şimdi bu sınırı elde etmeyi başaracağız. Yapmaya çalışacağımız şey, “N üzeri epsilon-tarzı-birleştirme-sıralaması” olacak; belli bir epsilon değeri için. Bu arada, M’nin en az  olduğunu varsayarsak,  epsilon üçte bir çıkar.

Öyleyse, “ küpkök-N-tarzı-birleştirme” yapacağız. Belirlenmiş bir sınırlama çerçevesinde, birleştirmenin nasıl yapıldığını bildiğimiz varsayımıyla,  sıralama algoritmalarını size vererek ve çözümlerini yaparak başlayacağım. Sonra birleştirmeyi yapacağız;  zor olan yanı,  birleştirme. Tamam, birleştirme..-- ilk önce size kara kutuyu vereyim. Her şeyden önce, birleştirme ne yapıyor? K tarzı birleştirmeye K hunisi deniyor, çünkü göreceğiniz gibi, aynı bir huni’ye benziyor. K hunisi bir veri yapısı veya veri yapısını andıran bir algoritmadır. Ve K-sıralamalı-listeleri birleştirir. Böylece, bir an için elinizde K listelerinin bulunduğunu, bunların sıralanmış ve nispeten uzun olduklarını düşünürsek, bu karakutu ile çalışmak ve sıralama yaptığımızda o listeleri elde edebilmek için de belli ek varsayımlara ihtiyacımız vardır. Ve sıraladıkça bunları elde edebileceğiz.

O listelerin toplam boyutunu istiyoruz. Tüm elemanları topluyorsunuz; bu listelerin en az   boyutunda olmaları gerek; varsayım bu. Sonra bu listeleri, temelde sıralama sınırını kullanarak, birleştiriyor.  Aslında, theta  demeliyim.  Bu boyuttan çok daha büyük olmasını da istemiyorum.  Bunun için özür dilerim. Böylece, bu birleştirici huni’nin kullandığı bellek transferlerinin sayısı: --  üzerindeki sıralama sınırı, yani  bölü B,  --  bölü B nin, M/B tabanındaki logaritması, -- artı başka bir K bellek transferidir.

K sayıda bellek transferi oldukça makuldür. Bu durumda en azından her listeyi okumaya başlamalı ve liste başına bir bellek transferi ödemelisiniz. Tamam, ama amacımız bir anlamda bu artı K’dan kurtulmak olacak.  Birleştirmeyi bu kadar süratli yapabiliriz; bunu  sonra yapacağız. Şimdi elimizde bunun olduğunu varsayarak, sıralamayı nasıl yapacağımızı anlatalım. Bu “Huni sıralaması” denen sıralama, sonuç olarak, yeterli. Fakat, bir anlamda, küp kök N tarzı birleştirme sıralaması.” Pekala, bunu bu durumu kullanarak analiz edeceğiz. Yani, Huni sıralamasında, K’ yi, küpkök N olarak tanımlayıp, bu birleştirmeyi uygulayacağız. Öyleyse ne yapıyoruz? Tıpkı burada olduğu gibi, dizilimimizi küpkök N boyutlu parçalara böleceğiz.

Bu  parçaların ardı ardına alt-dizilimler halinde olmaları gerektiğini söylüyorum. Bunlara dizilimin bölütleri yani “segments of the array” diyeceğim. Önbelleği dikkate almayan durumlarda, dizilimlerin ne şekilde düzenlenmiş oldukları gerçekten çok önemlidir. Dizilimleri kesecek ve birbirini takip eden küpkök N sayıda dizilim parçaları elde edeceğiz. Sonra onları, özyineleme yolu ile sıralayacağım, sonra da, birleştireceğim. Birleştirirken, K Hunisi’ni,  küpkök N hunisini  kullanacağım çünkü.--  Şimdi neden 1/ 3 kullanıyorum? Bu üç nedeniyle. Küpkök N hunisini kullanabilmek için, birleştirmeyi yaptığım elemanların toplam sayısının en az ’ün olmasını garanti etmem lazım. Bu sayının küpü de N dir. Bu da elimdeki elemanların kesin sayısı.

Bu huniyi kullanabileceğim koşulu tanımlar.. Küpkök N Hunisini kullanabilmem için elimde en az  elemanın olması gerekir.  Eğer böyle bir gereklilik olmasaydı, her biri bir boyutunda N listem var diyebilirdim. Bu durum ise bu birleşimde kesinlikle iyi çalışmaz. Sezgisel bakınca bu, artı K sizi öldürecektir. Bu Artı M ye dönüşecek ve çok büyüyecektir.

Ancak, bir küpkök N hunisi kullanabilir ve bu yoldan sıralama yapabiliriz. Öyleyse bu algoritmayı çözümleyelim. Umarım her şeyi doğru yaparsam sıralama sınırlarını verecektir. Bu oldukça kolaydır. Sıralama sınırını tekrar tekrar yazdığım için burası bayağı karışmış. Pekala, bu birleştirmenin maliyeti. Bu kökteki durum. Fakat  bu durumda N’dir. Öyleyse, özyinelemenin kökünde--  ama önce özyinelemeyi yazayım. Afedersiniz..  N eleman üzerinde, küpkök N sayıda bellek transferimiz var. Bunu doğru yazayım.  Evet, küpkök N  sayıda özyineleme, her biri N’nin 2/3 boyutunda, --tamam – artı bu zaman, ama K^3  N’ye eşit.

Böylece bu, artı N bölü B çarpı,-- N bölü B’nin M/B tabanındaki logaritması,-- artı M nin küpkökü… Bu da toplanır artı K’ lerim.. Öyleyse bu benim özyinelemem. Taban durumum her zamanki gibi..  MT belirli bir sabit çarpı M, yani M bölü B düzeyinde. Böylece burada neyi elde etmek istediğimizi  biliyoruz. Yoo.. Hiç de değil. Bundan önceki bütün yinelemelerde her düzeyde aynı maliyeti bulmuş ve log faktörümüzü bundan elde etmiştik. Şimdi bir log faktörümüz var bile, öyleyse, bir ikincisini çıkarmamalıyım.. Doğru mu?. Kanıtlamak istediğimiz sınır bu.  Şimdi burada bir saniye kopya çekmeme izin verin.

Evet, eminim-- bu küpkök N’nin oldukça büyük olmasına siz de şaşıyorsunuzdur. Eğer bundan daha büyük ise, özyinelemenin en üst düzeyinde başımız zaten dertte demektir. Şimdi ben bunun kabul edilebilir olduğunu iddia ediyorum.  Küpkök N’ye, bir bakalım. Burada bir taban şıkkı var ve N’nin tüm değerlerini, en çok belli bir sabitle çarpımı durumda tanımlıyor.. Eğer bu durumdaysam, N’ nin en az, önbelleğin bir sabitle çarpımı sonucunda olduğu kadar büyük olduğunu biliyorum.

Şimdi önbelleğin en az  olduğunu varsaymıştık. Eğer daha dikkatli olmak isterseniz, bunu B’nin bir artı epsilonuncu kuvveti ile de yapabilirsiniz. Böylece N en az dir, tamam mı? Bundan sonra bunlarla  başım hep derde girer. Böylece bu, N bölü B, yani karekök N’nin  omegasıdır. Burada pek çok şey söyleyebilirsiniz ama içlerinden sadece bir tanesi doğrudur. Öyleyse, neden? Bu, N’nin karekökünün, en az B olduğunu söylüyor; öyleyse B ile bölünmüş N, en çok N’nin karekökü ile bölünmüş N’ dir. O da en az N’nin karekökü  eder. Tabii, tüm bunları kontrol etmelisiniz. Burada aritmetiği oldukça hızlı geçeceğim çünkü sıkıcı,  ama gerekli. Pekala, N’nin karekökü,  N’nin küp kökünden  kesin  olarak daha büyüktür, bu tamam. Öyle ise, N bölü B  de N’nin küp kökünden kesinlikle daha büyüktür.

Burada, N bölü B çarpı bir’den daha büyük bir şey var. Yani bu örnekte bu terim, kesinlikle şu terime  hükmediyor. Taban durumu içinde olmadığım sürece, N’nin en az M düzeyinde olduğunu biliyorum. Bu terim benim özyinelememde kaybolur. Bu iyiydi. Şimdi elde etmek istediğimiz, bu toplam koşma zamanı. Özyineleme maliyeti küçük olsa iyi olacak; sabit faktörün buna göre artışından daha küçük olmalı..

Şimdi özyinelemeyi yazalım.,N / B N/B ‘yi kökte elde ediyoruz. Sonra bir sürü alt-probleme bölüyoruz, burada küp kök N sayıda alt-probleme ayırıyoruz. Ve her biri aslında buna mal oluyor,ancak ,N, N’nin 2/3’üncü kuvvetiyle yer değiştiriyor. Öyleyse,  log_M/B tabanında --,pardon burada B ile bölmeyi unutmuşum--, , bölü B: Bu düğümlerden birinin maliyeti—ve bunlardan küp kök N adet oluyor. Toplam olarak ne oluyorlar? Küpkök  N var,  var, bunlar çarpımda N olur. Böylece N bölü B elde ediyoruz. Bu fena, bu aynı görünüyor ve  biz başka log faktörü kaybetmek istemiyoruz. Ama iyi haber, burada bir adet üçte ikimiz var.

 Sonuçta bu düzeyde toplam olarak bunu elde ediyoruz. “Sorting bound yani Sıralama sınırına benziyor ama, logda hala bir üçteiki var. Şimdi, bir log’da üçteikinin kuvveti üçte iki çarpanı olarak dışarı çıkar. Öyleyse bu aslında:2/3 çarpı, N / B, -- (N/B) yani  sıralama sınırı olur. Bu ise, sıralama sınırının  üçte ikisine karşılık geliyor. Ve bu da sıralama sınırı, yani bir çarpı sıralama sınırı oluyor.

Demek ki, geometrik olarak küçülüyor.. Eveeet. Bunu ispatlamayacağım  ama doğrudur. Bu, 2/3 faktörü oranında azaldı, bir sonrakinin de 2/3 faktörü kadar azalacağı tümevarım ile anlaşılıyor. Yani bir düzeyde doğru olduğunu ispatladığınız şeyin, her düzeyde doğru olması gerekir. Buradaki ayrıntıları atlıyorum. Ama emin olmak için yaprak düzeyini kontrol edebiliriz. Bu daima iyi bir kontroldür. Yapraklarda, maliyetimizin M bölü B olduğunu biliyoruz.

Pekiyi kaç yaprak var? Tıpkı daha önceki gibi N/M yaprağımız var. Tamam öyleyse, en altta toplam maliyet N / B’dir. Ve bu da, elde edeceğinizle eşit olur. Esas itibariyle, sezgi yolu ile bunun bundan küçük olacağını düşündüğünüz için, garip gibi geliyor.Aslında değil. Gerçekte olan şey şu, elinizde N / B kere bu loglu şey var. Fazla aldırmadığımız için buna sadece ‘log’ diyelim.

Bir sonraki düzeyde ele aldığınız, o log’un üçte ikisi. Ve bir sonraki düzeyde, dokuzda dört kere o log ve bu böyle devam ediyor. Böylece, düzeylerin yükselmesine karşılık, log bire ininceye kadar, maliyeti geometrik olarak küçülüyor. Bundan sonra siz, özyinelemeyi durduruyorsunuz ve  N / B’ yi  en sonunda logsuz olarak elde ediyorsunuz. Başka bir deyişle, yaptığınız şey  N / B’yi  değil, log’u küçültmek. Üçte ikinin de, buralarda artık bitmiş olması gerekir. Gerçekte buradaki düzeylerin sayısı log log N.

Bu da sonunda bir elde edene kadar, ilk başta üş eşit parçaya böldüğünüz log’u, kaç kere bölmeniz gerektiğinin sayısıdır. Aslında ihtiyacımız olan bu değil. Geometrik küçülmede  kaç düzey olduğuyla ilgilenmeyiz. Sonsuza kadar pek çok düzey olabilir. Geometrik olarak azalıyor ve bunu koşma süresi olarak elde ederiz. MT(N), huni-sıralamasının sıralama sınırı oluyor. İşte bu mükemmel. Bu kadar hızlı birleştirme yapan bir huni elde edebildiğimiz sürece, yapabileceği kadar hızlı sıralama yapan bir sıralama algoritması elde ederiz. Bunu tahtaya yazmadım ama, bu asimptotik açıdan en iyi yani optimaldir. B ve M’nin ne olduklarını bilseniz bile, yapmayı ümit edebileceğiniz en iyi şey budur. Ve burada bunu B ve M ne olurlarsa olsun uyguluyoruz.

İyi. Şimdi huni için hazır olun. Huni bir başka özyineleme olacak. Bu bir özyinelemeli algoritma içindeki özyineleme algoritmasıdır. Bir başka böl-ve-fethet, bu derslerin başında gördüğümüz statik arama ağaçları benzeri. Yani bunların hepsi birbiriyle bağlantılı.. Pekala K hunisi,--  ona K hunisi diyorum çünkü bu onu, sadece küpkök N’de değil, belli bir özyinelemeli düzeyinde düşünmek istiyorum. Aslında, K hunisinin karekökünü özyinelemeli yoldan kullanacağız.  İşte o sınırı elde etmem gerekiyor. Özyineleme, statik arama ağacı gibi ve tek bir tahta üzerine çizimi biraz zor, ama işte başlıyoruz.                                                                                                          

Elimizde bir karekök K hunisi var; bu özyinelemeli.. Burada yukarıda bir tampon” buffer” yani arabellek var. Bunun adı çıkış tamponu yada arabelleği ve  boyutunda.. Ve sadece keyfine birazının dolu olduğunu varsayalım. Ve, başka arabelleklerin de olduğunu varsayalım. Ve bunların da farklı miktarla dolu olduklarını kabul edelim. Bunların her birinin boyutu, şüphesiz K  üzeri 3/2. Bu parçaların adı arabellek yada ara tampondur. Ve sonra onlardan sarkan başka huniler var. Karekök K-hunisi burada, bir karekök K-hunisi de burada, her arabellek için bir tane, bu huninin her çocuğu yani ardılı için bir tane.

Pekala, sonra bu hunilerden sarkan  giriş dizilimleri var. Tamam, onların K adedini burada çizecek değilim ama, çizmediğim K sayıda giriş dizilimi var, bunlara giriş listeleri diyelim ve onları en aşağıda gösterelim. Buradaki fikir, bunları aşağıdan yukarıya birleştirmek... Önce, enaz  toplam boyutlu olan  K-giriş-dizilimlerimizle başlayacağız. Burada yukarda bu kadar olduklarını varsayıyoruz. Onları,  K’nın karekökü  boyutundaki gruplar  halinde gruplaştırıyor ve grupların her birini, yani K’ nın karekökü boyutundaki gruplardan oluşan bu K-listelerini, özyineleme yoluyla birleştirecek olan bir karekök-K hunisinin içine atıyoruz. Bu hunilerin çıktısını, yanıtın ne olacağını belirlemek amacıyla bir arabellekte bir şekilde biriktiriyoruz. Diğer taraftan bu tamponlar, tam K üzeri 3/2 boyutunda olmalarına karşın, bu kusursuz bir depolama hacmi olmayabilir çünkü bunların içindeki  eleman sayısı ortalama K üzeri 3/2 – çünkü elde toplam   var ve karekök K sayıda grup var.

Özetle K^3 bölü K nın karekökü,  bu da ortalamada K’nin 3/2’inci kuvvetini verir. Ama, bunların bazıları daha büyük  bazıları daha küçük olacaklar. Buraya çizdim. Birleştirme şeklinize bağlı olarak bazıları daha fazla yer boşaltırlar. Ancak ortalamada bunların hepsi aynı zamanda dolacaklar. Sonra onları bir karekök K hunisinin içine sokacağız ve  çıktısını elde edeceğiz. Yani bu burada göreceğimiz olayların kabaca oluşma şekli.

Tamam ama, bunların bazıları önce de dolabilir ve o tamponu boşaltmak için belli miktar birleştirme yapmamız  ve gelmekte olan başka parçalara yer açmamız gerekir. Tablo işte bu. Şimdi, algoritmanın ne olduğunu söylemeden ve analizine geçmeden önce sadece alan üzerinde düşünün; Çok basit, ısınma amaçlı bir çözümleme olsun.. Haydi “Alan”a giriş, çıkış arabellekleri olmaksızın bakmaya çalışalım. Pekala, neden giriş ve çıkış arabelleklerini hariç tutmak istiyorum?  Çünkü , her arabelleği sadece bir defa saymak istiyorum.. Ve bu arabellek bunun için giriş, bunun için de çıkış. Yani bütün arabellekleri özyineleme yoluyla ve sadece bir defa saymak için, yalnızca bu ortadaki arabellekleri sayacağım. Ve giriş ve çıkış arabelleklerinin genelini ayrıca düşünmem gerekecek. Ama bu değerler zaten verilmiş gibi. Yani çıkış için,  ‘e ihtiyacım var, Giriş için de K^3. Öyleyse, bütünü düşünmeyi unutun. Böylece ortadaki arabellekleri özyinelemeli yoldan sayarsam, bütün arabellekleri elde etmiş olacağım.

Böylece  alan için çok basit bir özyineleme elde ederiz.  S(K)  yaklaşık olarak, karekök K + bir, çarpı S( karekök K)  + O().. Düzey , çünkü elimizde, her biri K üzeri 3/2 boyutunda karekök-K sayıda arabellek var. İnceleyin, sizce de doğru mu? Bu bayağı gibi görünüyor ama, sanırım doğru.Hayır, hayır doğru.Bu K üzeri 3/2 çarpı karekök K,-- o da K üzeri 3/2 artı yarım,-- bu da K üzeri 4/2 dır ve o da  eder  .Üfff…tamam, iyi. Sadece aritmetiğimde iyi değilim. Buradaki toplam tamponlama  K^2. Her düzeydeki özyineleme için bunları topluyorsunuz ve buradaki artı bir tepedeki elemanı, karekök K’ler alttaki elemanları hesaba katmak için yapılıyor ve karekök K  artı bir çıkıyor.

Eğer bunlar, -- bir dakika şuraya yineleme ağacını çizeyim. Bu yinelemeyi çözebilmeniz için pek çok yol var. En doğalı K’ye bakacağınız yerde log K’ye bakmanız, çünkü burada log K ikiye bölünüyor. Yineleme ağaçlarını hemen çizeyim ki  sezgiyi görebilin.  Ama  eğer bunu çözecekseniz logları kullanın. Böylece, karekök K artı bir, dallanma faktörü var.                                  

Bundan sonra  problem, karekök K boyutlu, öyleyse bu K olacak, hepsinin böyle olacağına inanıyorum. Bu karekök K’nin karesi alınıyor ve bu düzeylerin maliyeti oluyor. Ve böylece devam ediyorsunuz. --  En altın neye benzediğine  özellikle aldırmıyorum, çünkü en üstte elimizde  var.  Bu bize bir sonraki düzeyde maliyetin “K çarpı kök K artı bir” olarak veriyor. Sonraki düzeyin maliyeti K üzeri 3/2 artı K. Yani böylece,  ‘den,  K üzeri 3/2  artı K’ ya gidiyoruz. Bu bir süper-geometrik, üstel geometrik bir azalım gibi. Bu gerçekten çok hızlı azalıyor. Öyleyse, K^2 düzeyinde.. Bu benim “işim bittiği için el sallama” beyanım. Tamam mı? Öyleyse maliyet, temelde en üst düzeydeki önbelleklerin boyutu olur, yani toplam alan. Buna ihtiyacımız olacak. Bu aslında theta , çünkü burada bir artı theta ‘m var.

Zamanı hesaplayabilmemiz için böyle olması gerekiyor. O nedenle bunu söyledim. Alanın çok büyük olmaması iyi bir duygu değil. Aslında Huni, toplam giriş boyutundan çok daha küçük. Giriş boyutu, . Fakat bu, o kadar hayati değil. Önemli olan,  olması ve bunu çözümlemede  kullanmamız.Tamam. Normal olarak bu şey özyinelemeli olarak yerleştirilir. En üstteki huniyi özyinelemeli olarak depolarsınız.Sonra, bu örnekte her  arabelleği ardı ardına gelen bir dizilim şeklinde yazarsınız. .

Burada bir özyineleme yok. Böylece hepsini teker teker yazın..Sakın kendi aralarında serpiştirmeyin. Düzenli şekilde depolayın. Sonra, bu alttaki hunilerini de özyinelemeli şekilde yazın. Her huni, ardı ardına gelen bir bellek parçasıysa,  her arabellek ardı ardına gelen bellek parçaları olarak kalmaya devam ettiği sürece, bu işlemi her zaman özyinelemeli şekilde yapmalısınız. O zaman birazdan yapacağımız süre çözümlemesi çalışacaktır.

Pekala, çözümleyeceğimiz algoritmayı size vereyim. Huninin çalışması için, -- en başta bütün arabellekler boş olduğunu belirtiriz. Her şey en alttadır. Yapacağımız şey, “kök arabelleğini doldur”, demek. Bunu doldur. Bu özyinelemeli  algoritma ve bir arabelleğin nasıl doldurulacağının tanımını birazdan vereceğim. Bir kere dolduğunda, her şey yukarı çekilmiş ve birleştirilmiş demektir. Tamam, demek ki bu şekilde başlıyoruz. Özetle,  birleştirme demek;, “algoritmayı birleştir, en üstteki arabelleği, en üstteki çıkış tamponunu doldur,” demektir.

Tamam, bir arabelleği şöyle doldurursunuz. Genel olarak, bu özyinelemeyi yol boyunca genişletirseniz,-- taban şıkkında bahsetmemiştim, orada küçük bir düğüm elde edersiniz. Öyleyse, bu şekilde doldurmak istediğiniz rastgele bir tampona bakarsanız, -- mesela bu boş ve siz onu doldurmak istiyorsunuz, -- hemen altta, iki tane çocuğu, iki arabelleği olan bir köşe olacaktır.  Belki buna benziyor. Eşit boyutta olmaları dışında, ne kadar büyük olduklarını bilmiyorsunuz. Bundan çok daha küçük veya büyük olabilirler, bilmiyoruz.  Ama, ilk derslerimizde, ikili arama ağacı örneğinde yapmış olduğumuz gibi, siz de sonunda  bundan   bir ikili yapı elde edeceksiniz. Pekala, bu arabelleği nasıl dolduracağız? Sadece bu iki ardıl arabelleği mümkün olan en uzun süre birleştirerek...

Demek ki, bu iki ardıl arabelleği, boşalana  kadar birleştiriyoruz.  Böylece, genel değişmez,  bu arabelleğin,-- bunu bir cümle olarak yazayım. Bir tampon boş olmadığı sürece veya içinde olanlar daha kullanılmamışsa, altındaki alt-ağacın tamamının birleştirilmiş çıkışının bir ön-eki’dir. Böylece bu, aşağıdaki her şeyin kısmen birleştirilmiş alt-dizisi oluyor. Bu, buradaki her şeyin kısmen birleştirilmiş alt-dizisi.

Üstünden elemanları bir bir alarak birleştirme yapabilirim ve bu bana, bir tanesi boşalıncaya kadar oraya koymak üzere çıktılar verecektir. Ancak, önce hangisinin  boşalacağı, düzenine bağlı olduğundan bu konuda önceden bir fikrimiz olamaz.  Ne zaman biri boşalırsa, onu özyinelemeli olarak doldururuz. Hepsi bu kadar. Algoritma, bundan ibaret..

Ne zaman biri boşalırsa, özyineleme yoluyla onu dolduruyoruz. Taban durumu ve yapraklar bağlamında ise yapacak hiçbir şey yok gibi. Sanırım bir girdi listesinden doğrudan okursunuz. Böylece, en altta, eğer burada bu ikisi arasında birleştirme yapmaya  çalışan bir köşeniz varsa, bu iki listenin doğrudan birleştirilmesidir. İki paralel tarama ile bunun nasıl yapıldığını biliyorsunuz. Gerçekte buradaki şeyin tamamını birleştirebilir ve arabelleğe atabiliriz.Tabii bu arabelleğin ne büyüklükte olduğuna bağlı. Bunu sadece  arabellek  doluncaya kadar yapabiliriz.

Bir arabellek dolduğu anda dururuz ve özyineleme katmanlarını yukarı atarız.. Yani, doldurmak istediğimiz tampon arabellek doluncaya kadar bu birleştirmeyi yapıyoruz, sonra duruyoruz ve yukarı alıyoruz. Birleştirme ile ilgili algoritma bu. Şimdi, algoritmayı analiz etmemiz gerekiyor. Aslında çok zor değil, oldukça akıllı bir çözümlemesi var. Ve üstün yönü, bu bir amortizasyon, yani sizin tercih ettiğiniz yöntem. Böylece, önbelleği dikkate almayan algoritmalar bağlamında, amortize çözümlemede son bir pratik daha yapıyoruz. Ama bu biraz karmaşık olacak. Şimdiye kadar gördüğümüz tüm fikirleri bir araya getireceğiz. Gördüğümüz ana çözümleme fikri, bu özyinelemeyi yapı içinde yapıyoruz,-- eğer gözümüzün önüne getirirsek, K hunimizi alıyoruz, ortadan bölüyoruz, bir sürü karekök K hunisi oluşturuyoruz ve bu böyle devam ediyor; sonra, orta düzeyde olanları da kesiyoruz, dördüncü kökten K hunileri elde ediyoruz ve bu böyle sürüyor, -- belli bir noktada baktığımız huni, önbelleğe sığıyor.

Daha önce bir bloğa sığarsa demiştik. Şimdi, belli bir noktada “bu hunilerden biri önbelleğe sığacak”, diyeceğiz. O özyinelemenin detayı düzeyindeki hunilerin her biri önbelleğe sığacak. O düzeyi çözümleyeceğiz. O düzeye J diyoruz. Şimdi, o özyinelemenin ilk detay düzeyini düşünün ve bu düzeye J diyorum. -- Bu düzeyde sahip olduğumuz her J hunisi -- ve sadece bir tanesi değil, dört tanesi önbelleğe sığar.

Yani bir tanesi önbelleğin dörtte birine sığar. Ama önbelleğin bir kısmını yapılacak diğer işler için de ayırmamız lazım. Ayrıca, J hunisinin sığdığından emin olmak istiyorum. Şimdi bu ne demek oluyor?  Alan’ı çözümlemiştik. J  hunisinin alanının  kadar, belli bir sabit çarpı  olduğunu, biliyoruz.  Buna C çarpı , diyebiliriz. Öyle ise, bu C çarpı  , en çok M bölü 4, yani önbelleğin bir çeyreği eder demektir.

Yani bu boyuttaki bir J hunisi önbelleğin dörtte birini işgal eder, demektir. Özyinelemenin bir noktasında, bu büyük J hunileri ağacımız olacak ve aralarında bir sürü önbellek olmasına karşın, her J hunisinin sığacağını göreceğiz. Şimdi, J hunilerinden sadece bir tanesini düşünün. J karekök K gibi bir şey olsun. Bu şekli kullanalım, aksi halde  daha büyük bir şekil çizmem gerekecek. , J hunisinin bu olduğunu düşünün, giriş arabellekleri var ve bir çıkış arabelleği var.

Bu durumda J hunisinin nasıl görev yaptığını düşünmeye çalışalım. Uzun süre, bu tamponlar dolu kaldıkça, bu bir birleşmedir. Bu özyinelemeyle yapılıyor ama biz aslında buna aldırmıyoruz.Bu şeyin tümü değişir değişmez,--  aslında bunu çizmem lazım, huninin ,çıkış tamponu, giriş tamponu devreye girdiğinde, başka bir deyimle o blokların hepsini içeri getiriyorsunuz,-- sadece birleştirme yapar ve bir şey boşalıncaya veya çıkışı dolduruncaya kadar, mutlu birleştirme işlemine devam edebilirsiniz.

Öyleyse, bunu da çözümleyelim. Her şeyin bellekte olduğunu farz edin çünkü sığdığını biliyoruz. Pekala, biraz daha dikkatli olmam lazım. Giriş arabelleklerinin toplam boyutları aslında oldukça büyük, çünkü buradaki toplam boyut,K’nın 3/2’nci kuvveti iken--  burada karekök K. Bu aslında K boyutunda. Genel bir şekil çizeyim. Bir J hunimiz var, -- aksi halde aritmetik bayağı karışacak. 

 Bir J hunimiz var. Boyutunun C çarpı  olduğunu sanıyoruz. Girişlerin sayısı J ve -- boyutları oldukça büyük. Nerede böyle tanımlamıştık? Bir K hunimiz var. Toplam giriş boyutu  . Öyle ise J için , bu  olacak. Önbelleğin tamamını, bunu depolamaya, ayıramayız. O J’nin ekstra bir faktörüdür. Ama her giriş için bir blok yer ayırabiliriz. Birleştirme için tüm ihtiyacımız bu. Ben bu giriş dizilimlerinin her ilk bloğunu, J hunisi ile aynı zamanda, önbelleğe sığdırabileceğimi iddia ediyorum. Ve böylece o süre içinde her şey önbellekte kaldığı sürece, paralel taramalarda yaptığımız gibi, tam hızla birleşebilecektir. Burada aşağıda bulunan tüm bu blokları yukarda kullanınca, bir tanesi boşalıyor ve giriş arabelleğinde bir sonraki  bloğa gidiyorsunuz ve bu böyle devam ediyor; tıpkı paralel dizilimlerin normal birleştirme çözümlerinde olduğu gibi, bu evrede buradaki her şeyin önbelleğe sığdığını varsayıyoruz.

 Aynen önceki gibi. Elbette, aslında bu da özyinelemeli ama, bu düzeyde analiz ediyoruz. Şimdi, giriş başına bir bloğu sığdırabileceğimizi ispatlamam lazım. Zor değil. sadece hesaplama. Ve temelde bu hunilerin düzenleme şekilleri sayesinde,  her giriş arabelleği başına bir blok sığdırabiliyorsunuz. İşte tartışma konumuz. Öyleyse iddia, “önbelleğe her giriş arabelleği başına, bir bellek bloğu da sığdırabilirsiniz” şeklinde. Bu bir J hunisindekine ek olarak yapılıyor. J hunisinde de her giriş  arabelleği  başına da bir blok sığdırabilirsiniz. Tamam, bu J hunisiyle ilgili olan kısım.

Aslında herhangi bir huni değil çünkü daha büyük huniler, bazen gerçekten çok büyüktür.  Nasıl ispatlayacağımıza geçersek,   en çok dörtte bir M ediyor. Burada varsaydığımız buydu; aslında  C   idi. Burada C ile ilgilenmeyeceğim çünkü sadece hayatımı daha güçleştirir. Kanımca bu daha zayıf bir sınırlama. Hunimizin boyutu dir. Bu önbelleğin en fazla bir çeyreği olur. Her iki tarafın karekökünü alırsak, J en çok, ½  karekök M eder. Beri yandan B’nin en çok karekök M olduğunu, çünkü M’ nin en az B kare olduğunu biliyoruz. Böylece yan yana koyduğumuzda J çarpı B, en fazla yarım M ediyor.

Şimdi, istediğimizin J kere B olduğunu, çünkü bir J hunisinde, J sayıda giriş diziliminin bulunduğunu iddia ediyorum. Öyleyse her biri için bir blok isterseniz bu, her biri için B alanı kadar bir maliyet eder. Yani, her arabellek girişi için, B boyutunda bir bloğumuz var, ve iddia da, her şeyin önbelleğin yarısına sığacağı idi. Oysa, önbelleğin sadece dörtte birini kullandık. Öyleyse, toplam olarak önbelleğin üç çeyreğini kullanmış oluyoruz.Bu da kullanacağımızın tamamı olur.Öyleyse bu iyi haber. Kalanla çıkışa bir blok daha sığdırabiliriz. Bu da çok büyük bir iş değil.

Netice olarak, bu J hunisi çalıştığı sürece her şey önbellekte ise, her şey yolunda demektir. Bunun anlamı nedir? Önce bu hunide değişimin ne kadar süre aldığını çözümleyeyim. Soru, bir J hunisindeki herşeyi ve arabellek başına bir bloktaki herşeyi okumak ne kadar zaman alıyor? Başlamak için gerekli olan bu. Bu J hunisi içindeki değişim oluyor, yani J hunisinin tamamını okumak ve  her giriş başına bir blok okumak. Değişimin maliyeti oldukça normal,--.arabelleğin boyutunun B’ye bölünmesi, çünkü okumak için sadece doğrusal tarama gerekir ve -- arabellek başına bir blok okumamız gerekiyor.

Bu tamponlar çok büyük oldukları için, her yere dağılmış durumda olabilirler. Öyleyse, başlangıçta ilk bloğu okumak için, giriş başına bir bellek transferi ödüyoruz diyelim. İddia, -- burada  biraz  daha aritmetik yapmamız gerekiyor. Bu en çok  bölü B dir. Neden en fazla  bölü B?  Bu önbelleğe sığan şeylerin bulunduğu ve önbelleğe sığdığı birinci düzeydi. Bu ikinci düzey daha büyük demektir ki, o  dir. Bunun boyutu  tür ve bu önbellekten daha büyük olmalıdır. Aksi takdirde durmanız gerekecekti. Bu sadece biraz daha aritmetik. Ya bana inanır ya da aritmetiği takip edersiniz. ’ün en az M -- ve M’nin de en az   olduğunu biliyoruz. Bundan dolayı,  yerine yi koyup, iki tarafın karekökünü aldığımızda, J^2 en az B olur.

Böylece elbette,  bölü B, en çok  bölü B olur. Fakat J de en çok  bölü B dir, çünkü  en az B’dir. Umarım bunların hepsi açık çünkü sadece cebir. Bu sınırlamayı biraz karışık olduğu için kullanmayacağız. Sadece  bölü B’nin değişiminin maliyeti olduğunu söyleyeceğiz. Niçin  bölü B iyi bir şeydir? Çünkü J hunisine girişlerin toplam boyutunun  olduğunu biliyoruz. Öyleyse, J hunisinde ki tüm girdileri okumak J^3 bölü B süre alır. Aslında bu her şeyin değiştirilmesi için doğrusal ve ek bir maliyet oluyor. Kulağa iyi geliyor. Birleşmeyi yapmak da  bölü B’ye mal olur. Yani tüm bu J^3  elemanı birleştirmek için, değişim  bölü M ye mal oluyor. Eğer hepsi orada girişlerde olsaydı,  bölü B zaman alacaktı çünkü, bir kere her şey orada olduğunda ve tam sürat birleştirme yaptığınızda, bunu ortalamada, bellek başına B öğesi olarak yapıyorsunuz.

Ama sorun tahmin ettiğiniz gibi, değişimi yaparken bulunduğunuz yerden de çıkmanızın gerektiği. Giriş arabelleklerinizden biri boşalır boşalmaz, -- bu boşalmak üzere diyelim, boşalır boşalmaz o huniyi tamamen yok edecek ve içindeki bütün parçaları birleştirmek ve bu arabelleği ağzına kadar doldurmak için, bunun içine değişim yapacaksınız. Amortizasyon bu noktada işin içine girer. Şimdiye kadar esas itibariyle doğrusal maliyet ödemiş olduğumuz için, log faktörü de işin içine girer.

Neredeyse bitirdik. Böylece uyguladığımız bedel, -- af edersiniz, kendimin önümde koşuyorum. -- Bir giriş arabelleği boşaldığında -- biz de dışarı çıkıyor ve o arabelleği özyinelemeli olarak dolduruyoruz. Tüm bu işlemler sırasında, tekrar-kullanımın hiçbir şekilde olmadığını varsayıyorum, yani bu özyinelemeli doldurma her şeyi dışarı çıkardı ve bu huni için her şeye sıfırdan başlamam gerekiyor. Böylece bu olduğunda, bu tamponu dolduruyorum ve sonra-- geri geliyorum ve “bunun içini yeniden doldurup değiştireyim”, diyorum. Özyineleme çağrısı biter bitmez yeniden içinde değiş tokuş yapıyorum. Yani, özyinelemeli olarak önce dolduruyorum, sonra da içindekileri değiştiriyorum.

Tekrar içini yeniden doldurup değiştirmek,  bölü B ye mal oluyor. Bu maliyeti henüz dolmuş olan elemanlara uygulayacağım. İşte bu bir “amortised charging argument”, yani amortize edilmiş fiyatlama argümanı’dır. --- Bunlardan kaç tane var?  Tek soru bu. Herşey çok yolunda görünüyor, buradaki karekök K hunisi için her arabellek K^ 3/2 boyutunda; aslında bu biraz karmaşık. Ama ben arabelleği dolduran buradaki elemanların sayısının  olduğunu iddia ediyorum. Yani “eğer bir J huniniz varsa, her giriş arabelleğinin  boyutu ’dür. Eğer hesaplarsanız doğru olması lazım. Böylece,  bölü B maliyetini,  sayıda elemana yüklüyoruz. Bu da eleman başına, bir bölü B gibi bir şey oluyor. 

Mükemmel görünüyor. Bu,  problemi bütünüyle düşündüğümüzü gösteriyor, yani N sayıda eleman var ve bunların her birine, bir bölü B fiyatı uyguluyorsunuz. Bu, toplam koşma zamanının N bölü B gibi bir değer olduğunu ifade eder. Sıralama için biraz fazla hızlı.  log faktörünü kaybettik. Böylece olan şey, aslında bir elemana birden fazla kez maliyet yüklüyoruz. Normalde bu yapmadığımız bir şey. Bu sınıfta hiç yapmadık. Ancak bunu, maliyet yükleme sayısını sınırladığınız takdirde yapabiliyorsunuz. Bir maliyet yükleme işlemi yaptığınızda, “Bu her yerde çok sayıda tekrarlamıyor, çünkü bu olduğunda şu oluyor.” diyebilirsiniz. Ama asıl yapmanız gereken, maliyeti elemanlara yüklediğinizde, bunu belli elemanlara çok da fazla uygulamadığınızı ispat etmek olmalıdır. Benim burada üzerine maliyet yükleyebileceğim ölçeklenebilir şeylerim var: elemanlar. Öyleyse, “bu arabelleğin içine girmiş her eleman için, eleman başına bir bölü B maliyeti uygulayacağım’’ diyorum.

Bu elemanlara kaç kere maliyet yüklenir? Her maliyet yüklendiğinde, yeni bir arabelleğe taşınıyor. Pekiyi, kaç arabellek değiştirebilir? Her zaman sadece yukarı doğru çıkıyor. Birleştirme daima yukarıya çıkar. Yani buradan başlarız, bir sonraki arabelleğe gidersiniz, sonra da bir sonrakine..  Ziyaret ettiğiniz arabelleklerin sayısı, log..-- doğru log’dur. Hangi log olduğunu bilmiyorum. Bir bölü B maliyetinin eleman başına yüklenme sayısı, o elemanın arabelleği ziyaret sayısıdır ve bu bir log faktördür. Koşma zamanı içindeki ek log faktörünü bu noktada elde ederiz. Ziyaret edebileceğiniz J hunilerinin düzeylerinin sayısı budur. Yani, log K bölü log J dir, eğer doğru yaptıysam.

Pekala, bitirdik gibi. Biraz toparlayalım . Sadece biraz daha aritmetik, maalesef. Son olarak log K bölü log J demiştik. Şimdi,   kabaca M gibidir; M’nin karekökü olabilir. Ama log J temelde log M’dir. Orada bazı sabitler var. Öyle ise, burada elemanlara maliyet yükleme sayısı, teta logK bölü log M’dir. Bu, amortizasyonda pek görmediğimiz bir şey ama, toplam bedel yükleme sayısını bulmak için toplamak zorundasınız. Tüm işin maliyeti birilerine yükleniyor, sadece başlangıçtaki değişimleri hiç kimseye yüklemedik. Ama, her değiş tokuşta bunu birine yüklüyoruz. Öyleyse her şey kaç kere ücretlendiriliyor?  N elemanı var. Herbiri bir bölü B maliyetinde; ücretlendirme sayısı da bu log K bölü log M kadar.

O nedenle toplam maliyet -- elemanların sayısı çarpı bir bölü B çarpı bu log’lu şeydir. Bu da aslında artı K dir. Bir artı K’ yi unuttuk ama bu en başta tüm giriş listelerinde işe başlamakla ilgiliydi. Bu, bu sınırı ispatlamak için yapılan bir amortizasyon çözümlemesidir.. Af edersiniz, buradaki N de ne?  En altta, K^3 sayıda elemanla başladığımı varsaymıştım. En alttaki elemanların sayısı K^3 theta idi. N değil  K^3 yazmalıydım . Bu, bununla  aşağı yukarı aynı olmalı-- ama tamamen aynı değil.. Bu log_M/K tabanında, -- biraz aritmetik yaparsanız, bunun : K^3 bölü B, çarpı log_M/B tabanında K bölü B, artı K  olması gerekiyor.

İspatlamak istediğim şey bu. Aslında burada bir K yerine K^3 var. Fakat bu, sadece üçün bir faktörü. Ve bu takip ediyor çünkü taban durumunda olmadığımızı varsayıyoruz. Böylece K  en az M oluyor, bu da en az  demek ve bu sebepten, K bölü B, omega karekök K oluyor. Öyleyse, K bölü B, esas itibariyle bir log’a yerleştirdiğinizde K ile aynı gibidir. Şimdi burada log M tabanı var. Ben onu log M bölü B tabanına çevirdim. Bu daha da kötü oldu. Zarar yok. Ve K’nin log’u var. Onu da K bölü  B ile değiştirdim ama K bölü B, aslında K nın karekökü. Yani, bir log içinde sadece yarımın bir faktörü olur.

 Böylece, bu huninin çözümlemesi tamamlanıyor. Bu delice koşma zamanını elde ediyoruz, ve bu aslında sıralama sınırı artı küçük  bir değer. Onu huni sıralamasına uyguladığımızda, sihirli bir şekilde önbelleği dikkate almayan en iyi sıralamayı elde ediyoruz; tam zamanında.

Salı günü final var. Sınav daha ziyade birinci Quiz stilinde, yani çok fazla yaratıcılığı yok, genellikle işlenen konulara yönelik. Her şeyi kapsıyor. Huni sıralaması konusunda endişelenmenize gerek yok ama geri kalan her şeyi kapsıyor. Birinci Quiz gibi ama bütün yarıyıl için.

Üç saat sürecek ve iyi şanslar. Sizinle olmak bir zevkti, tüm öğrenciler. Eminim Charles da öyle düşünüyordur, bu nedenle herkese teşekkürler.

Çok eğlenceli idi.