โดยปกติแล้วฟังก์ชันแฮชแบบง่ายจะทำงานโดยการใช้ "ส่วนประกอบส่วนต่าง ๆ " ของอินพุต (อักขระในกรณีของสตริง) และคูณด้วยอำนาจของค่าคงที่และเพิ่มเข้าด้วยกันในรูปแบบจำนวนเต็ม ดังนั้นตัวอย่างเช่นแฮชทั่วไป (แม้ว่าจะไม่ค่อยดี) ของสตริงอาจเป็น:
(first char) + k * (second char) + k^2 * (third char) + ...
จากนั้นถ้ากลุ่มของสตริงทั้งหมดที่มีอักขระตัวแรกเหมือนกันถูกป้อนเข้าผลลัพธ์จะเป็นโมดูโล k เดียวกันอย่างน้อยที่สุดจนกว่าชนิดจำนวนเต็มจะล้น
[เป็นตัวอย่างสตริง hashCode ของ Java นั้นคล้ายกันมากกับสิ่งนี้ - มันใช้อักขระเรียงลำดับย้อนกลับโดยมี k = 31 ดังนั้นคุณจะได้รับความสัมพันธ์ที่โดดเด่น modulo 31 ระหว่างสตริงที่จบในลักษณะเดียวกันและความสัมพันธ์ที่น่าประทับใจแบบโมดูโล 2 ^ 32 ระหว่างสตริงที่เหมือนกันยกเว้นใกล้ถึงจุดสิ้นสุด สิ่งนี้จะไม่ทำให้พฤติกรรมแฮชโต๊ะยุ่งเหยิงอย่างจริงจัง]
hashtable ทำงานโดยใช้โมดูลัสของแฮชกับจำนวนของที่เก็บข้อมูล
สิ่งสำคัญใน hashtable ไม่ควรสร้างการชนในกรณีที่เป็นไปได้เนื่องจากการชนจะลดประสิทธิภาพของ hashtable
ตอนนี้สมมติว่ามีบางคนใส่ค่าทั้งหมดไว้ใน hashtable ที่มีความสัมพันธ์ระหว่างรายการเช่นเดียวกับที่มีอักขระตัวแรก นี่เป็นรูปแบบการใช้งานที่คาดเดาได้ฉันจะพูดดังนั้นเราจึงไม่ต้องการให้เกิดการชนกันมากเกินไป
ปรากฎว่า "เพราะธรรมชาติของคณิตศาสตร์" ถ้าค่าคงที่ที่ใช้ในแฮชและจำนวนของถังเป็นcoprimeการชนจะลดลงในบางกรณีที่พบบ่อย หากพวกเขาไม่ใช่coprimeดังนั้นจึงมีความสัมพันธ์ที่ค่อนข้างง่ายระหว่างอินพุตที่ไม่ได้ลดการชน แฮชทั้งหมดออกมาเป็นโมดูโลเท่า ๆ กันซึ่งเป็นปัจจัยทั่วไปซึ่งหมายความว่าพวกมันทั้งหมดจะตกอยู่ใน 1 / n ของถังที่มีค่านั้นโมดูโลเป็นปัจจัยร่วม คุณได้รับการชนหลายครั้งโดยที่ n เป็นปัจจัยทั่วไป ตั้งแต่ n อย่างน้อย 2 ฉันจะบอกว่ามันไม่เป็นที่ยอมรับสำหรับกรณีการใช้งานที่ค่อนข้างง่ายในการสร้างการชนกันอย่างน้อยสองเท่าตามปกติ หากผู้ใช้บางคนจะแบ่งการกระจายของเราเป็นที่เก็บข้อมูลเราต้องการให้มันเป็นอุบัติเหตุประหลาดไม่ใช่การใช้งานที่คาดเดาได้ง่าย
ตอนนี้การใช้งาน hashtable เห็นได้ชัดว่าไม่มีการควบคุมรายการที่ใส่ไว้ในรายการ พวกเขาไม่สามารถป้องกันพวกเขาที่เกี่ยวข้อง ดังนั้นสิ่งที่ต้องทำคือทำให้แน่ใจว่าค่าคงที่และจำนวนถังเป็น coprime ด้วยวิธีนี้คุณไม่ต้องพึ่งพาส่วนประกอบ "สุดท้าย" เพียงอย่างเดียวเพื่อกำหนดโมดูลัสของถังด้วยความเคารพต่อปัจจัยทั่วไปเล็กน้อย เท่าที่ฉันรู้ว่าพวกเขาไม่จำเป็นต้องเป็นคนสำคัญในการทำสิ่งนี้
แต่ถ้าฟังก์ชั่นแฮชและแฮชตารางถูกเขียนขึ้นมาอย่างอิสระแฮชตารางจะไม่รู้ว่าฟังก์ชั่นแฮชทำงานอย่างไร มันอาจจะใช้ค่าคงที่กับปัจจัยเล็ก ๆ หากคุณโชคดีอาจทำงานได้ไม่เหมือนกันและไม่เชิงเส้น หากแฮชดีพอการนับจำนวนถังใด ๆ ก็ถือว่าใช้ได้ แต่ hashtable หวาดระแวงไม่สามารถรับฟังก์ชั่นแฮชที่ดีได้ดังนั้นควรใช้จำนวนมากของที่เก็บข้อมูล ในทำนองเดียวกันฟังก์ชั่นแฮชแบบหวาดระแวงควรใช้ค่าคงที่จำนวนมากที่มีขนาดใหญ่เพื่อลดโอกาสที่บางคนใช้ถังจำนวนหนึ่งซึ่งเกิดขึ้นเพื่อมีปัจจัยร่วมกับค่าคงที่
ในทางปฏิบัติฉันคิดว่ามันค่อนข้างปกติที่จะใช้กำลัง 2 เป็นจำนวนของถัง สะดวกและประหยัดไม่ต้องค้นหารอบ ๆ หรือเลือกจำนวนเฉพาะที่มีขนาดสำคัญ ดังนั้นคุณต้องพึ่งพาฟังก์ชั่นแฮชที่จะไม่ใช้ตัวคูณแม้กระทั่งซึ่งโดยทั่วไปจะเป็นสมมติฐานที่ปลอดภัย แต่คุณยังสามารถรับพฤติกรรมการแฮ็กที่ไม่ดีเป็นครั้งคราวโดยใช้ฟังก์ชันแฮชเช่นเดียวกับข้างบนและการนับจำนวนเฉพาะกลุ่มอาจช่วยเพิ่มเติมได้
เกี่ยวกับหลักการที่ว่า "ทุกอย่างจะต้องมีความสำคัญ" เท่าที่ฉันรู้เพียงพอ แต่ไม่ใช่เงื่อนไขที่จำเป็นสำหรับการกระจายที่ดีในแฮชเทเบิล ช่วยให้ทุกคนทำงานร่วมกันโดยไม่จำเป็นต้องคิดว่าคนอื่นปฏิบัติตามกฎเดียวกัน
[แก้ไข: มีอีกเหตุผลที่พิเศษกว่าคือการใช้ถังจำนวนมากซึ่งก็คือถ้าคุณจัดการการชนด้วยการตรวจวัดเชิงเส้น จากนั้นคุณคำนวณความก้าวหน้าจาก hashcode และหากความก้าวหน้านั้นเป็นปัจจัยของการนับ bucket คุณสามารถทำได้เฉพาะโพรบ (bucket_count / stride) ก่อนที่คุณจะกลับมาเริ่มต้นใหม่ กรณีที่คุณต้องการหลีกเลี่ยงมากที่สุดคือ stride = 0 ซึ่งต้องเป็นแบบพิเศษ แต่เพื่อหลีกเลี่ยงการใส่ปลอกพิเศษ bucket_count / stride เท่ากับจำนวนเต็มเล็ก ๆ คุณสามารถทำให้ bucket_count เป็นไพร์มและไม่สนใจว่า การก้าวเดินให้ไม่ได้ 0]