डेविड रिचेर्बी के जवाब पर विस्तार करने के लिए, " हैश फ़ंक्शन " शब्द थोड़ा अतिभारित है। अक्सर, जब हम एक हैश फ़ंक्शन के बारे में बात करते हैं, तो हम एमडी 5, एसएचए -1, या जावा के .hashCode()
तरीके के बारे में सोचते हैं , जो कुछ इनपुट को एक ही संख्या में बदल देता है। हालाँकि इस नंबर का डोमेन (यानी अधिकतम मूल्य है) उसी आकार का होने की संभावना नहीं है जिस हैशटेबल में आप डेटा स्टोर करने की कोशिश कर रहे हैं (MD5 16 बाइट्स है, SHA-1 20 बाइट्स है, और .hashCode()
एक int
- 4 है बाइट्स)।
तो आपका प्रश्न उस अगले चरण के बारे में है - एक बार जब हमारे पास एक हैश फ़ंक्शन होता है जो संख्याओं के लिए मनमाना इनपुटों को मैप कर सकता है, तो हम उन्हें किसी विशेष आकार के डेटा संरचना में कैसे डालते हैं? एक अन्य फ़ंक्शन के साथ, जिसे "हैश फ़ंक्शन" भी कहा जाता है!
इस तरह के एक फ़ंक्शन का एक तुच्छ उदाहरण modulo है ; आप आसानी से modulo के साथ एक सरणी में एक विशिष्ट सूचकांक के लिए कई मनमाने आकार का नक्शा कर सकते हैं। इसे CLRS में "विभाजन विधि" के रूप में पेश किया गया है:
में विभाजन विधि हैश फंक्शन बनाने के लिए, हम एक कुंजी के नक्शे में से एक में के शेष लेने के द्वारा स्लॉट्स से विभाजित । यानी हैश फंक्शन हैएम के एमkmkm
mh(k)=k mod ।m
...
विभाजन पद्धति का उपयोग करते समय हम आमतौर पर कुछ मूल्यों से बचते हैं । उदाहरण के लिए, 2 के एक शक्ति नहीं होना चाहिए, अगर बाद से तो बस है का सबसे कम क्रम बिट्स ।m m = 2 p h ( k ) p kmmm=2ph(k)pk
~ एल्गोरिदम का परिचय, .311.3.1 - सीएलआरएस
इसलिए मोडुलो एक शानदार हैश फ़ंक्शन नहीं है, क्योंकि यह प्रतिबंधित करता है कि हम अपने अंतर्निहित डेटा संरचना के लिए सुरक्षित रूप से किन आकारों का उपयोग कर सकते हैं। अगला खंड एक अधिक जटिल "गुणन विधि" का परिचय देता है, जो मोडुलो का भी उपयोग करता है, लेकिन लाभप्रद है क्योंकि " का मूल्य महत्वपूर्ण नहीं है"। हालांकि यह "डेटा की विशेषताओं के कुछ पूर्व ज्ञान के साथ सबसे अच्छा काम करता है" - ऐसा कुछ जिसे हम अक्सर नहीं जानते हैं।m
जावा HashMap
डिवीजन विधि के एक संशोधित संस्करण का उपयोग करता है जो कमजोर .hashCode()
कार्यान्वयन के लिए एक पूर्व-प्रसंस्करण कदम करता है ताकि यह पावर-ऑफ-टू आकार सरणियों का उपयोग कर सके। आप देख सकते हैं कि वास्तव में .getEntry()
विधि में क्या हो रहा है (टिप्पणियाँ मेरी हैं):
// hash() transforms key.hashCode() to protect against bad hash functions
int hash = (key == null) ? 0 : hash(key.hashCode());
// indexOf() converts the resulting hash to a value between 0 and table.length-1
for (Entry<K,V> e = table[indexFor(hash, table.length)];
...
जावा 8 एक फिर से लिखना के साथ लाया गया है HashMap
जो और भी तेज है, लेकिन पढ़ने में थोड़ा कठिन है। हालाँकि, यह इंडेक्स लुकअप के लिए समान सामान्य सिद्धांत का उपयोग करता है।