Kovalar çok fazla dolarsa, o zaman
çok uzun bağlantılı bir liste.
Ve bu bir nevi noktayı yenmek.
İşte dört kovamın olduğu bir örnek.
Şu ana kadar HashSet'imde fil ve porsuk var.
Bu oldukça iyi bir durum, değil mi?
Her öğenin sıfır veya bir öğesi vardır.
Şimdi HashSet'imize iki öğe daha ekledik.
buckets elements
------- -------
0 elephant
1 otter
2 badger
3 cat
Bu da fena değil.
Her kova sadece bir elemana sahiptir. Eğer bilmek istersem, bu panda içerir mi?
Çok hızlı bir şekilde kova 1'e bakabilirim ve değil
orada ve
Koleksiyonumuzda olmadığını biliyorum.
Eğer kedi içerip içermediğini bilmek istersem, kovaya bakarım
3 numara,
Kedi buluyorum, çok çabuk biliyorum ki bizim
Toplamak.
Ya koala eklersem, o kadar da kötü değil.
buckets elements
------- -------
0 elephant
1 otter -> koala
2 badger
3 cat
Belki şimdi 1 numaralı kova yerine sadece
bir eleman,
Twokisine bakmam gerek.
Ama en azından fil, porsuk ve
kedi.
Yine panda arıyorum, sadece kovada olabilir
1 numara ve
Su samuru dışında başka bir şeye bakmak zorunda değilim ve
koala.
Ama şimdi timsahı 1 numaralı kovaya koydum ve sen
bakın belki nereye gidiyor.
1 numaralı kova gittikçe büyüyor ve
daha büyük, o zaman temelde tüm
bulmak için bu unsurlar
1 numaralı kovada olması gereken bir şey.
buckets elements
------- -------
0 elephant
1 otter -> koala ->alligator
2 badger
3 cat
Diğer kovalara dize eklemeye başlarsam,
doğru, sorun her geçen gün daha da büyüyor
tek kova.
Kovalarımızın çok fazla dolmasını nasıl önleyebiliriz?
Buradaki çözüm
"the HashSet can automatically
resize the number of buckets."
HashSet, kovaların
çok dolu.
Tüm bu aramaların bu avantajını kaybediyor
elementler.
Ve sadece daha fazla kova oluşturacak (genellikle eskisinden iki kez) ve
ardından elemanları doğru kovaya yerleştirin.
İşte temel HashSet uygulamamız ayrı
zincirleme. Şimdi bir "kendini yeniden boyutlandıran HashSet" oluşturacağım.
Bu HashSet, kovaların
çok dolmak ve
daha fazla kovaya ihtiyacı var.
loadFactor, HashSet sınıfımızdaki başka bir alandır.
loadFactor başına ortalama öğe sayısını temsil eder
Kova,
üzerinde yeniden boyutlandırmak istiyoruz.
loadFactor, mekan ve zaman arasındaki bir dengedir.
Kovalar çok dolarsa yeniden boyutlandırırız.
Bu elbette zaman alıyor, ama
kovalar bir
biraz daha boş.
Bir örnek görelim.
İşte bir HashSet, şu ana kadar dört öğe ekledik.
Fil, köpek, kedi ve balık.
buckets elements
------- -------
0
1 elephant
2 cat ->dog
3 fish
4
5
Bu noktada, loadFactor,
eşik,
her bir kova için iyi olduğum ortalama öğe sayısı
ile, 0.75.
Kova sayısı kovadır. 6 olan uzunluk ve
bu noktada HashSet'imizin dört öğesi vardır, yani
geçerli boyut 4'tür.
HashSet'imizi yeniden boyutlandıracağız, yani daha fazla kova ekleyeceğiz,
grup başına ortalama öğe sayısı aşıldığında
loadFactor.
Geçerli boyutun kovalara bölünmesi budur. Uzunluk
loadFactor'dan daha büyük.
Bu noktada, kova başına ortalama öğe sayısı
4 bölü 6'dır.
4 element, 6 kova, bu 0.67.
Bu, 0,75 olarak belirlediğim eşikten daha az.
Tamam.
Yeniden boyutlandırmaya ihtiyacımız yok.
Ama şimdi diyelim ki dağ sıçanı ekliyoruz.
buckets elements
------- -------
0
1 elephant
2 woodchuck-> cat ->dog
3 fish
4
5
Woodchuck, kova numarası 3 ile sonuçlanacaktı.
Bu noktada currentSize 5'tir.
Ve şimdi kova başına ortalama öğe sayısı
currentSize öğesinin buckets.length değerine bölünmesiyle elde edilen değerdir.
Bu 5 elementin 6 kovaya bölünmesi 0.83'tür.
Bu da 0.75 olan loadFactor'u aşıyor.
Bu sorunu çözmek için,
kovalar belki biraz
işlemlerin daha
kova içerir
bir element biraz daha az karmaşık olacak, yeniden boyutlandırmak istiyorum
HashSet'im.
HashSet'i yeniden boyutlandırmak iki adım alır.
İlk önce kova sayısını ikiye katlayacağım, 6 kova vardı,
Şimdi 12 kepçem olacak.
Burada 0.75 olarak ayarladığım loadFactor'un aynı kaldığını unutmayın.
Ancak değiştirilen kova sayısı 12'dir,
aynı kalan eleman sayısı 5'tir.
5 bölü 12 yaklaşık 0.42, bu bizim
Yük faktörü,
şimdi iyiyiz.
Ama işimiz bitmedi çünkü bu öğelerin bazıları
yanlış kova şimdi.
Örneğin fil.
Fil 2 numaralı kovadaydı çünkü
fil karakterleri
8 idi.
6 kepçemiz var, 8 eksi 6 2.
Bu yüzden 2 numaraya çıktı.
Ama şimdi 12 kova var, 8 mod 12 8, yani
fil artık kova numarası 2'ye ait değil.
Fil, kova numarası 8'e aittir.
Dağ sıçanı ne olacak?
Tüm bu soruna başlayan Woodchuck'tı.
Woodchuck 3 numaralı kepçeyle sonuçlandı.
Çünkü 9 mod 6 3'tür.
Ama şimdi 9 mod 12 yapıyoruz.
9 mod 12 9'dur, dağ sıçanı 9 numaralı kovaya gider.
Ve tüm bunların avantajını görüyorsunuz.
Şimdi 3 numaralı kova sadece iki öğeye sahipken, daha önce 3'e sahipti.
İşte kodumuz,
HashSet'imizi ayrı zincirleme ile
yeniden boyutlandırma yapmadı.
Şimdi, yeniden boyutlandırma kullandığımız yeni bir uygulama.
Bu kodun çoğu aynı,
hala içerdiği
değer zaten.
Değilse, hangi kovayı koyacağımızı anlayacağız
girmeli ve
daha sonra bu bölüme ekleyin, bu LinkedList'e ekleyin.
Ama şimdi currentSize alanını artırıyoruz.
currentSize, sayıyı takip eden alandı
HashSet'imizdeki öğelerin
Onu artıracağız ve sonra bakacağız
ortalama yükte,
grup başına ortalama öğe sayısı.
Bu bölümü burada yapacağız.
Emin olmak için burada biraz döküm yapmalıyız
bir çift olsun.
Ve sonra, bu ortalama yükü alanla karşılaştıracağız
olarak belirlediğim
Örneğin, bu HashSet'i oluşturduğumda 0.75
loadFactor.
Ortalama yük loadFactor'dan büyükse,
bu, kova başına çok fazla öğe olduğu anlamına gelir
ve yeniden yerleştirmem gerekiyor.
İşte yeniden yerleştirme yöntemini uygulama
tüm öğeleri.
İlk olarak, oldBuckets adlı yerel bir değişken oluşturacağım.
Şu anda durdukları kovalara atıfta bulunuyor
her şeyi yeniden boyutlandırmaya başlamadan önce.
Not Henüz yeni bir bağlantılı listeler dizisi oluşturmuyorum.
Sadece kovaları eski kovalar olarak yeniden adlandırıyorum.
Şimdi kovaların sınıfımızdaki bir alan olduğunu hatırlıyorum
şimdi yeni bir dizi oluşturmak için
Bağlantılı listelerin% 100'üne eşittir, ancak bunun iki katı öğe
ilk kez yaptığı gibi.
Şimdi yeniden yerleştirmeyi yapmalıyım,
Tüm eski kovaları tekrarlayacağım.
OldBuckets içindeki her öğe bir LinkedList dizesidir
bu bir kova.
O kovadan geçeceğim ve içindeki her elemanı alacağım
Kova.
Ve şimdi yeni kovalara tekrar yerleştireceğim.
Onun hashCode'unu alacağım.
Hangi indeks olduğunu anlayacağım.
Ve şimdi yeni bir kova alıyorum, yeni LinkedList
teller ve
Onu yeni kovaya ekleyeceğim.
Özetlemek gerekirse, gördüğümüz gibi HashSets, Linked dizileri
Listeler veya bölümler.
Kendini yeniden boyutlandıran HashSet, bir oran veya
capacity = N/0.75
yeniden şekillenmeyi önlemek için belirtmeyi önermektedir, ancak ilk düşüncem yeni ayarlanmıştıload factor = 1
. Bu yaklaşımın dezavantajları olur mu? Yük faktörü neden etkiget()
veput()
işletme maliyetlerini etkiler ?