ถ้าถังเต็มเกินไปเราต้องมองผ่าน
รายการเชื่อมโยงที่ยาวมาก
และนั่นคือการเอาชนะประเด็น
นี่คือตัวอย่างที่ฉันมีสี่ถัง
ฉันมีช้างและแบดเจอร์ในแฮชเซ็ตของฉันจนถึงตอนนี้
นี่เป็นสถานการณ์ที่ดีทีเดียว
แต่ละองค์ประกอบมีศูนย์หรือหนึ่งองค์ประกอบ
ตอนนี้เราได้เพิ่มองค์ประกอบสองอย่างเข้าไปใน HashSet ของเรา
buckets elements
------- -------
0 elephant
1 otter
2 badger
3 cat
นี่มันก็ไม่ได้แย่เหมือนกัน
ถังทุกอันมีองค์ประกอบเดียวเท่านั้น ถ้าฉันอยากรู้มันมีแพนด้าอยู่ไหม?
ฉันสามารถดูหมายเลขถัง 1 อย่างรวดเร็วและไม่ใช่
ที่นั่นและ
ฉันรู้ว่ามันไม่ได้อยู่ในคอลเลกชันของเรา
ถ้าฉันอยากรู้ว่ามันมีแมวอยู่หรือเปล่า
หมายเลข 3
ฉันพบแมวฉันรู้ว่ามันอยู่ในนั้นหรือไม่
ชุด
ถ้าฉันเพิ่มโคอาล่าแล้วล่ะก็มันก็ไม่เลว
buckets elements
------- -------
0 elephant
1 otter -> koala
2 badger
3 cat
อาจจะตอนนี้แทนที่จะเป็นที่ฝากข้อมูลหมายเลข 1 เท่านั้นที่ดู
องค์ประกอบหนึ่ง
ฉันต้องดูสองคน
แต่อย่างน้อยฉันก็ไม่จำเป็นต้องดูช้างตัวแบดเจอร์และ
แมว.
ถ้าฉันกำลังมองหาหมีแพนด้าอีกครั้งมันจะอยู่ในถังเท่านั้น
หมายเลข 1 และ
ฉันไม่ต้องมองอะไรเลยนอกจากนากแล้ว
สัตว์มีถุงหน้าท้องคล้ายหมี
แต่ตอนนี้ฉันใส่จระเข้ในถังหมายเลข 1 แล้วคุณก็ทำได้
ดูบางทีสิ่งนี้กำลังจะไป
นั่นคือถ้าถังหมายเลข 1 ใหญ่ขึ้นเรื่อย ๆ และ
ที่ใหญ่กว่านั้นฉันต้องมองผ่านทั้งหมด
องค์ประกอบเหล่านั้นเพื่อค้นหา
สิ่งที่ควรอยู่ใน bucket จำนวน 1
buckets elements
------- -------
0 elephant
1 otter -> koala ->alligator
2 badger
3 cat
ถ้าฉันเริ่มเพิ่มสตริงลงในที่เก็บข้อมูลอื่น
ถูกต้องปัญหาใหญ่ขึ้นเรื่อย ๆ ในทุก ๆ
ถังเดียว
เราจะหยุดถังของเราให้เต็มได้อย่างไร?
ทางออกที่นี่ก็คือ
"the HashSet can automatically
resize the number of buckets."
มี HashSet ตระหนักว่าถังกำลังได้รับ
เต็มเกินไป
มันสูญเสียความได้เปรียบจากการค้นหานี้ทั้งหมด
องค์ประกอบ
และมันจะสร้างถังมากขึ้น (โดยทั่วไปเป็นสองเท่าก่อนหน้านี้) และ
จากนั้นวางองค์ประกอบลงในที่ฝากข้อมูลที่ถูกต้อง
ดังนั้นนี่คือการติดตั้ง HashSet พื้นฐานของเราด้วยการแยก
การผูกมัด ตอนนี้ฉันกำลังจะสร้าง "HashSet ที่ปรับขนาดตัวเอง"
HashSet นี้จะรู้ว่าถังบรรจุนั้น
รับเต็มเกินไปและ
มันต้องการถังเพิ่ม
loadFactor เป็นอีกฟิลด์หนึ่งในคลาส HashSet ของเรา
loadFactor แสดงถึงจำนวนเฉลี่ยขององค์ประกอบต่อ
ถัง,
ด้านบนซึ่งเราต้องการปรับขนาด
loadFactor คือความสมดุลระหว่างพื้นที่และเวลา
หากถังเต็มเกินไปเราจะปรับขนาด
แน่นอนว่าต้องใช้เวลา แต่
มันอาจช่วยเราประหยัดเวลาในการเดินทางหากถังเก็บน้ำเป็น
ที่ว่างเปล่าน้อยมาก
ลองดูตัวอย่าง
นี่คือ HashSet เราได้เพิ่มองค์ประกอบสี่อย่างแล้ว
ช้าง, สุนัข, แมวและปลา
buckets elements
------- -------
0
1 elephant
2 cat ->dog
3 fish
4
5
ณ จุดนี้ฉันได้ตัดสินใจแล้วว่า loadFactor, the
เกณฑ์
จำนวนเฉลี่ยขององค์ประกอบต่อถังที่ฉันโอเค
ด้วยคือ 0.75
จำนวนของถังคือที่เก็บข้อมูลความยาวซึ่งคือ 6 และ
ณ จุดนี้ HashSet ของเรามีองค์ประกอบสี่อย่างดังนั้น
ขนาดปัจจุบันคือ 4
เราจะปรับขนาด HashSet ของเรานั่นคือเราจะเพิ่มที่เก็บข้อมูลเพิ่มเติม
เมื่อจำนวนเฉลี่ยขององค์ประกอบต่อถังมากกว่า
loadFactor
นั่นคือเมื่อขนาดปัจจุบันหารด้วยที่เก็บข้อมูลความยาวคือ
มากกว่า loadFactor
ณ จุดนี้จำนวนเฉลี่ยขององค์ประกอบต่อถัง
คือ 4 หารด้วย 6
4 องค์ประกอบ 6 ถังนั่นคือ 0.67
นั่นน้อยกว่าขีด จำกัด ที่ฉันตั้งไว้ที่ 0.75 เราก็เลย
ตกลง.
เราไม่จำเป็นต้องปรับขนาด
แต่ตอนนี้สมมติว่าเราเพิ่ม woodchuck
buckets elements
------- -------
0
1 elephant
2 woodchuck-> cat ->dog
3 fish
4
5
Woodchuck จะจบลงด้วยหมายเลขถัง 3
ณ จุดนี้ขนาดปัจจุบันคือ 5
และตอนนี้จำนวนเฉลี่ยขององค์ประกอบต่อถัง
คือขนาดปัจจุบันหารด้วยที่เก็บข้อมูลความยาว
นั่นคือ 5 องค์ประกอบหารด้วย 6 ถังคือ 0.83
และสิ่งนี้สูงกว่า loadFactor ซึ่งเท่ากับ 0.75
เพื่อที่จะแก้ไขปัญหานี้เพื่อที่จะทำให้
ถังอาจจะเล็กน้อย
ว่างมากขึ้นเพื่อให้การดำเนินงานเช่นการพิจารณาว่า
ถังบรรจุ
องค์ประกอบจะซับซ้อนน้อยกว่าเล็กน้อยฉันต้องการปรับขนาด
HashSet ของฉัน
การปรับขนาด HashSet มีสองขั้นตอน
ก่อนอื่นฉันจะเพิ่มจำนวนถังเป็นสองเท่าฉันมี 6 ถัง
ตอนนี้ฉันจะมี 12 ถัง
โปรดทราบที่นี่ว่า loadFactor ที่ฉันตั้งไว้ที่ 0.75 ยังคงเหมือนเดิม
แต่จำนวนถังเปลี่ยนเป็น 12
จำนวนองค์ประกอบยังคงเหมือนเดิมคือ 5
5 หารด้วย 12 มีค่าประมาณ 0.42 ซึ่งอยู่ภายใต้เรา
loadFactor,
ดังนั้นเราโอเคตอนนี้
แต่เราไม่ได้ทำเพราะองค์ประกอบเหล่านี้บางอย่างอยู่
ตอนนี้ผิดถัง
ตัวอย่างเช่นช้าง
ช้างอยู่ในถังหมายเลข 2 เพราะจำนวน
ตัวละครในช้าง
เท่ากับ 8
เรามี 6 ฝาก 8 ลบ 6 คือ 2
นั่นเป็นเหตุผลที่มันลงเอยในหมายเลข 2
แต่ตอนนี้เรามีถัง 12 ถัง 8 mod 12 คือ 8 ดังนั้น
ช้างไม่ได้อยู่ในถังหมายเลข 2 อีกต่อไป
ช้างอยู่ในถังหมายเลข 8
สิ่งที่เกี่ยวกับ woodchuck
Woodchuck เป็นคนที่เริ่มต้นปัญหาทั้งหมดนี้
Woodchuck จบลงด้วยหมายเลขถัง 3
เพราะ 9 mod 6 คือ 3
แต่ตอนนี้เราทำ 9 mod 12
9 mod 12 คือ 9, woodchuck ไปที่ bucket จำนวน 9
และคุณเห็นข้อได้เปรียบทั้งหมดนี้
ตอนนี้หมายเลขถัง 3 เท่านั้นมีสององค์ประกอบในขณะที่ก่อนมี 3
นี่คือรหัสของเรา
ที่เรามี HashSet ของเราด้วยการผูกมัดที่แยกต่างหาก
ไม่ได้ทำการปรับขนาด
ตอนนี้นี่คือการใช้งานใหม่ที่เราใช้การปรับขนาด
รหัสนี้ส่วนใหญ่เหมือนกัน
เราจะยังคงตรวจสอบว่ามันมี
คุ้มค่าแล้ว
หากไม่เป็นเช่นนั้นเราจะหาว่าถังใด
ควรเข้าไปและ
จากนั้นเพิ่มลงในที่ฝากข้อมูลนั้นเพิ่มไปยัง LinkedList นั้น
แต่ตอนนี้เราเพิ่มฟิลด์ขนาดปัจจุบัน
currentSize คือฟิลด์ที่ติดตามจำนวน
ขององค์ประกอบใน HashSet ของเรา
เรากำลังจะเพิ่มมันแล้วเราจะไปดู
ที่ภาระเฉลี่ย
จำนวนเฉลี่ยขององค์ประกอบต่อถัง
เราจะทำส่วนนั้นลงที่นี่
เราต้องทำการคัดเลือกนักแสดงที่นี่เพื่อให้แน่ใจ
ที่เราได้รับสองเท่า
จากนั้นเราจะเปรียบเทียบโหลดเฉลี่ยกับฟิลด์
ที่ฉันตั้งไว้
0.75 เมื่อฉันสร้าง HashSet นี้ซึ่งก็คือ
loadFactor
หากโหลดเฉลี่ยมากกว่า loadFactor
นั่นหมายความว่ามีองค์ประกอบต่อถังมากเกินไป
โดยเฉลี่ยและฉันต้องการแทรกอีกครั้ง
ดังนั้นนี่คือการดำเนินการตามวิธีการของเราเพื่อแทรกเข้าไปใหม่
องค์ประกอบทั้งหมด
ก่อนอื่นฉันจะสร้างตัวแปรท้องถิ่นชื่อว่า oldBuckets
ซึ่งหมายถึงถังที่พวกเขายืนอยู่ในขณะนี้
ก่อนที่ฉันจะเริ่มปรับขนาดทุกอย่าง
หมายเหตุฉันยังไม่ได้สร้างรายการลิงก์ที่เรียงลำดับใหม่
ฉันแค่เปลี่ยนชื่อถังเป็นถังขยะเก่า
ตอนนี้จำได้ว่าถังเป็นทุ่งในชั้นเรียนของเราฉันจะไป
เพื่อสร้างอาร์เรย์ใหม่
ของรายการที่ลิงก์ แต่สิ่งนี้จะมีองค์ประกอบสองเท่า
เหมือนครั้งแรกที่ทำ
ตอนนี้ฉันต้องทำการ reinserting จริง ๆ
ฉันจะทำซ้ำผ่านถังเก่าทั้งหมด
แต่ละองค์ประกอบใน oldBuckets เป็น LinkedList ของสตริง
นั่นคือถัง
ฉันจะผ่านที่ฝากข้อมูลนั้นและรับองค์ประกอบแต่ละอย่างในนั้น
ถัง.
และตอนนี้ฉันจะใส่เข้าไปใน Buckets ใหม่
ฉันจะรับ hashCode ของมัน
ฉันจะหาว่าเป็นดัชนีใด
และตอนนี้ฉันได้ถังใหม่แล้ว LinkedList ใหม่ของ
สตริงและ
ฉันจะเพิ่มลงในถังใหม่
ดังนั้นในการสรุป HashSets อย่างที่เราเห็นคือ Array of Linked
รายการหรือถัง
HashSet ที่ปรับขนาดตัวเองสามารถตระหนักถึงการใช้อัตราส่วนหรือ
capacity = N/0.75
เพื่อหลีกเลี่ยงการ rehashingload factor = 1
แต่คิดเริ่มต้นของฉันได้เพียงแค่ตั้ง จะมีข้อเสียสำหรับวิธีการนั้นหรือไม่? ทำไมปัจจัยโหลดจะส่งผลกระทบget()
และput()
ค่าใช้จ่ายในการดำเนินงาน?