Nếu xô quá đầy, thì chúng ta phải xem qua
một danh sách liên kết rất dài.
Và đó là loại đánh bại điểm.
Vì vậy, đây là một ví dụ nơi tôi có bốn thùng.
Tôi có con voi và con lửng trong Hashset của tôi cho đến nay.
Đây là một tình huống khá tốt, phải không?
Mỗi phần tử có 0 hoặc một phần tử.
Bây giờ chúng tôi đặt thêm hai yếu tố vào Hashset của chúng tôi.
buckets elements
------- -------
0 elephant
1 otter
2 badger
3 cat
Điều này cũng không tệ lắm.
Mỗi thùng chỉ có một yếu tố. Vì vậy, nếu tôi muốn biết, điều này có chứa gấu trúc?
Tôi có thể nhanh chóng nhìn vào cái xô số 1 và nó không
ở đó và
Tôi biết nó không có trong bộ sưu tập của chúng tôi.
Nếu tôi muốn biết nó có chứa mèo không, tôi nhìn vào cái xô
số 3,
Tôi tìm thấy con mèo, tôi rất nhanh biết nếu nó ở trong chúng ta
bộ sưu tập.
Điều gì sẽ xảy ra nếu tôi thêm koala, điều đó không tệ lắm.
buckets elements
------- -------
0 elephant
1 otter -> koala
2 badger
3 cat
Có lẽ bây giờ thay vì trong xô số 1 chỉ nhìn vào
một yếu tố
Tôi cần nhìn vào hai.
Nhưng ít nhất tôi không phải nhìn vào con voi, con lửng và
con mèo.
Nếu tôi lại tìm gấu trúc, nó chỉ có thể ở trong thùng
số 1 và
Tôi không phải nhìn bất cứ thứ gì khác sau đó rái cá và
koala.
Nhưng bây giờ tôi đặt cá sấu vào thùng số 1 và bạn có thể
xem có thể nơi này sẽ đi.
Rằng nếu xô số 1 cứ ngày càng lớn hơn và
lớn hơn, về cơ bản tôi phải xem qua tất cả
những yếu tố cần tìm
một cái gì đó nên có trong xô số 1.
buckets elements
------- -------
0 elephant
1 otter -> koala ->alligator
2 badger
3 cat
Nếu tôi bắt đầu thêm chuỗi vào các nhóm khác,
đúng, vấn đề ngày càng lớn hơn
xô đơn.
Làm thế nào để chúng ta ngăn chặn xô của chúng tôi quá đầy?
Giải pháp ở đây là
"the HashSet can automatically
resize the number of buckets."
Có Hashset nhận ra rằng các thùng đang nhận được
quá đầy đủ
Đó là mất lợi thế của tất cả một trong những tìm kiếm này
các yếu tố.
Và nó sẽ chỉ tạo ra nhiều thùng hơn (thường gấp đôi so với trước đây) và
Sau đó đặt các yếu tố vào thùng chính xác.
Vì vậy, đây là triển khai Hashset cơ bản của chúng tôi với riêng biệt
xích Bây giờ tôi sẽ tạo ra một "Hashset tự thay đổi kích thước".
Hashset này sẽ nhận ra rằng các thùng là
quá đầy đủ và
nó cần nhiều xô hơn
loadFactor là một lĩnh vực khác trong lớp Hashset của chúng tôi.
loadFactor đại diện cho số phần tử trung bình trên mỗi
Gầu múc,
ở trên mà chúng tôi muốn thay đổi kích thước.
loadFactor là sự cân bằng giữa không gian và thời gian.
Nếu xô quá đầy thì chúng tôi sẽ thay đổi kích thước.
Điều đó cần có thời gian, tất nhiên, nhưng
nó có thể giúp chúng ta tiết kiệm thời gian xuống đường nếu xô là
thêm một chút trống rỗng.
Hãy xem một ví dụ.
Đây là Hashset, chúng tôi đã thêm bốn yếu tố cho đến nay.
Voi, chó, mèo và cá.
buckets elements
------- -------
0
1 elephant
2 cat ->dog
3 fish
4
5
Tại thời điểm này, tôi đã quyết định rằng loadFactor,
ngưỡng,
số lượng phần tử trung bình trên mỗi thùng mà tôi ổn
với, là 0,75.
Số lượng xô là buckets.length, là 6 và
tại thời điểm này, Hashset của chúng tôi có bốn yếu tố, vì vậy
kích thước hiện tại là 4.
Chúng tôi sẽ thay đổi kích thước Hashset của chúng tôi, đó là chúng tôi sẽ thêm nhiều nhóm hơn,
khi số lượng phần tử trung bình trên mỗi thùng vượt quá
loadFactor.
Đó là khi kích thước hiện tại chia cho buckets.length là
lớn hơn loadFactor.
Tại thời điểm này, số phần tử trung bình trên mỗi thùng
là 4 chia cho 6.
4 yếu tố, 6 thùng, đó là 0,67.
Đó là ít hơn ngưỡng tôi đặt là 0,75 vì vậy chúng tôi
Được chứ.
Chúng tôi không cần thay đổi kích thước.
Nhưng bây giờ hãy nói rằng chúng ta thêm woodchuck.
buckets elements
------- -------
0
1 elephant
2 woodchuck-> cat ->dog
3 fish
4
5
Woodchuck sẽ kết thúc trong xô số 3.
Tại thời điểm này, kích thước hiện tại là 5.
Và bây giờ số lượng phần tử trung bình trên mỗi thùng
là kích thước hiện tại chia cho buckets.length.
Đó là 5 yếu tố chia cho 6 thùng là 0,83.
Và điều này vượt quá loadFactor là 0,75.
Để giải quyết vấn đề này, để thực hiện
xô có lẽ một chút
trống hơn để các hoạt động như xác định xem một
xô chứa
một yếu tố sẽ ít phức tạp hơn một chút, tôi muốn thay đổi kích thước
Hashset của tôi.
Thay đổi kích thước Hashset mất hai bước.
Đầu tiên tôi sẽ nhân đôi số thùng, tôi có 6 thùng,
Bây giờ tôi sẽ có 12 thùng.
Lưu ý ở đây là loadFactor mà tôi đặt thành 0,75 giữ nguyên.
Nhưng số lượng thùng thay đổi là 12,
số phần tử giữ nguyên, là 5.
5 chia cho 12 là khoảng 0,42, đó là dưới của chúng tôi
hệ số tải,
Vì vậy, bây giờ chúng tôi ổn.
Nhưng chúng tôi không hoàn thành vì một số yếu tố này nằm trong
xô sai bây giờ.
Ví dụ, con voi.
Voi đã ở trong thùng số 2 vì số lượng
nhân vật trong voi
được 8.
Chúng ta có 6 thùng, 8 trừ 6 là 2.
Đó là lý do tại sao nó kết thúc ở số 2.
Nhưng bây giờ chúng ta có 12 thùng, 8 mod 12 là 8, vì vậy
voi không thuộc xô số 2 nữa.
Voi thuộc thùng số 8.
Còn gỗ thì sao?
Woodchuck là người bắt đầu toàn bộ vấn đề này.
Woodchuck đã kết thúc trong xô số 3.
Vì 9 mod 6 là 3.
Nhưng bây giờ chúng tôi làm 9 mod 12.
9 mod 12 là 9, woodchuck đi đến xô số 9.
Và bạn thấy lợi thế của tất cả điều này.
Bây giờ xô số 3 chỉ có hai yếu tố trong khi trước đó nó có 3.
Vì vậy, đây là mã của chúng tôi,
nơi chúng tôi đã có Hashset với chuỗi kết nối riêng biệt
đã không làm thay đổi kích thước.
Bây giờ, đây là một triển khai mới, nơi chúng tôi sử dụng thay đổi kích thước.
Hầu hết các mã này là như nhau,
chúng tôi vẫn sẽ xác định xem nó có chứa
giá trị rồi.
Nếu không, chúng ta sẽ tìm ra cái xô nào
nên đi vào và
sau đó thêm nó vào nhóm đó, thêm nó vào LinkedList đó.
Nhưng bây giờ chúng tôi tăng trường currentSize.
currentSize là trường theo dõi số
các yếu tố trong Hashset của chúng tôi.
Chúng tôi sẽ tăng nó và sau đó chúng tôi sẽ xem xét
ở mức tải trung bình,
số lượng phần tử trung bình trên mỗi thùng.
Chúng tôi sẽ làm điều đó xuống đây.
Chúng tôi phải thực hiện một chút đúc ở đây để đảm bảo
rằng chúng tôi nhận được gấp đôi.
Và sau đó, chúng tôi sẽ so sánh tải trung bình đó với trường
mà tôi đã đặt là
0,75 khi tôi tạo Hashset này, ví dụ, đó là
loadFactor.
Nếu tải trung bình lớn hơn loadFactor,
điều đó có nghĩa là có quá nhiều yếu tố trên mỗi thùng
trung bình, và tôi cần phải xác nhận lại.
Vì vậy, đây là việc chúng tôi thực hiện phương pháp để xác nhận lại
Tất cả các yếu tố.
Đầu tiên, tôi sẽ tạo một biến cục bộ có tên oldBuckets.
Đó là đề cập đến các thùng như họ hiện đang đứng
trước khi tôi bắt đầu thay đổi kích thước mọi thứ.
Lưu ý Tôi chưa tạo một mảng mới của danh sách được liên kết.
Tôi chỉ đổi tên xô thành oldBuckets.
Bây giờ hãy nhớ xô là một lĩnh vực trong lớp của chúng tôi, tôi sẽ
bây giờ tạo một mảng mới
danh sách được liên kết nhưng điều này sẽ có gấp đôi số yếu tố
như nó đã làm lần đầu tiên
Bây giờ tôi cần thực sự làm lại,
Tôi sẽ lặp đi lặp lại qua tất cả các thùng cũ.
Mỗi phần tử trong oldBuckets là một ListList của chuỗi
đó là một cái xô
Tôi sẽ đi qua cái xô đó và lấy từng phần tử trong đó
Gầu múc.
Và bây giờ tôi sẽ lắp lại nó vào newBuckets.
Tôi sẽ nhận được mã băm của nó.
Tôi sẽ tìm ra nó là chỉ số nào.
Và bây giờ tôi nhận được nhóm mới, LinkedList mới của
chuỗi và
Tôi sẽ thêm nó vào cái xô mới đó.
Vì vậy, để tóm tắt lại, HashSets như chúng ta đã thấy là các mảng của Liên kết
Danh sách, hoặc xô.
Một Hashset tự thay đổi kích thước có thể nhận ra bằng cách sử dụng một số tỷ lệ hoặc
capacity = N/0.75
để tránh luyện tập lại, nhưng suy nghĩ ban đầu của tôi mới được đặt raload factor = 1
. Sẽ có nhược điểm cho cách tiếp cận đó? Tại sao yếu tố tải ảnh hưởngget()
vàput()
chi phí vận hành?