क्यों (टक्कर-कम) हैशटेबल लुकिंग वास्तव में हे (1) है?


10

डिस्क्लेमर: मुझे पता है कि पहले से ही यहां और स्टाॅकओवरफ्लो पर ऐसे ही लगने वाले सवाल हैं। लेकिन वे सभी टकरावों के बारे में हैं, जो कि मैं नहीं पूछ रहा हूं।

मेरा प्रश्न है: क्यों collision- है कम देखने O(1)पहली जगह में?

मान लेते हैं कि मेरे पास यह हैशटेबल है:

Hash  Content
-------------
ghdjg Data1
hgdzs Data2
eruit Data3
xcnvb Data4
mkwer Data5
rtzww Data6

अब मैं उस कुंजी की तलाश कर रहा हूँ kजहाँ हैश फ़ंक्शन h(k)देता है h(k) = mkwer। लेकिन लुकअप "कैसे" जानता है कि हैश mkwer5 स्थिति पर है? इसे O(n)खोजने के लिए सभी कुंजियों को स्क्रॉल करने की आवश्यकता क्यों नहीं है? हैश असली हार्डवेयर पते के कुछ प्रकार नहीं हो सकता क्योंकि मैं डेटा को स्थानांतरित करने के लिए संयम खो दूँगा। और जहां तक ​​मुझे पता है, हैशटेबल को हैश पर नहीं सुलझाया जाता है (यदि ऐसा होता, तो खोज भी होती O(log n))।

एक हैश जानने से तालिका में सही जगह खोजने में कैसे मदद मिलती है?

जवाबों:


25

हैश फ़ंक्शन कुछ स्ट्रिंग जैसे कि वापस नहीं करता हैmkwer । यह सरणी में आइटम की स्थिति को सीधे लौटाता है। यदि, उदाहरण के लिए, आपकी हैश तालिका में दस प्रविष्टियाँ हैं, हैश फ़ंक्शन 0–9 की सीमा में पूर्णांक लौटाएगा।


1
धन्यवाद। :) मेरी गलती MD5 या SHA जैसे हैशटेबल हैश फ़ंक्शन के बारे में सोच रही थी। लेकिन एक हैश बेशक एक पूर्णांक स्थिति हो सकती है, जिसके बारे में मैंने नहीं सोचा था। अब जब मुझे पता है कि मुझे क्या देखना है, तो मुझे जल्दी से एक अच्छा उदाहरण मिला: PHP का हैश फ़ंक्शन: github.com/php/php-src/blob/PHP-5.6.10/Zend/zend_hash.n#L237
Foo बार

13
@FooBar: MD5 और SHA इनपुट से एकल नंबरों की गणना करते हैं, हेक्स रूप में हैश के बारे में बात करना इतना सामान्य है। जैसे स्मृति पतों को शायद ही कभी दशमलव में माना जाता है।
nperson325681

4
इसके अलावा, एमडी 5 आदि एक सरणी इंडेक्स के रूप में सीधे उपयोग किए जाने के लिए बहुत लंबे हैं। हैश के कुछ हिस्से का उपयोग करना संभव होगा, जैसे निचले एन बिट्स।
चिरलू ३१'१६

6

हैश फ़ंक्शन दी गई स्ट्रिंग से सरणी स्थिति की गणना करता है । यदि यह एकदम सही हैश है तो इसका मतलब है कि निश्चित रूप से कोई टकराव नहीं है, सबसे संभव है कि सरणी तत्वों की संख्या से कम से कम दोगुना बड़ा हो।


x=0;
x=xmod52

यह बहुत ही सरल हैश (सीमित और टकराव की संभावना) हैशिंग के तंत्र में अन्य हैश से भिन्न होता है, दिए गए इनपुट पर विचार नहीं करता है। अधिक उन्नत योजना में हैश बड़ी संख्या में है, तत्वों की संख्या से समायोजित। बिना किसी टकराव की गारंटी के सभी इनपुट के लिए परफेक्ट हैश उत्पन्न किया जाता है।

O(1)

h(k)

nthn(sizeofelement)


1
और कैसे पता देखने करता है जहां हैश तालिका में है? यह न तो आदेश दिया गया है और न ही हार्डवेयर पते।
फू बार

आप कुछ स्ट्रिंग देते हैं जैसे "xcnvb", इसलिए गणना की गई हैश सरणी का इंडेक्स देता है, "xcnvb" आपके लुकअप का तत्व है, 8 टेबल में इंडेक्स है। यह आदेश दिया गया है, हैश वापस लेने योग्य तत्व के लिए जगह देता है। इस तत्व को उसी फ़ंक्शन द्वारा रखा गया था। हार्डवेयर का यहां कोई लेना-देना नहीं है। आप सरणी में सूचकांक प्राप्त करने के लिए सरणी, हैश फ़ंक्शन और कम्प्यूट हैश प्रदान करते हैं, वही रेट्रिवल में। एरियर को क्रमबद्ध नहीं किया गया है, यह भी कभी भरा नहीं है। h("xcnvb")=8
ईविल

लेकिन हर इंडेक्स नहीं भरा जाएगा। अगर मेरे पास हैश 1, 4, 8, 90 और 223 डेटा से भरा है, तो लुकअप सही जगह कैसे खोजता है? Thsi केस ​​इंडेक्स "90" में स्थिति 4 पर है क्योंकि अधिकांश अन्य इंडेक्स मौजूद नहीं हैं। और एक खाली हैशटेबल सभी संभावित पदों वाले अनंत आकार का नहीं है !?
1938 में फू बार

हाँ, सरणी हमें 512 तत्वों को लंबे समय तक मानती है, 9 बिट्स हैश फ़ंक्शन के लिए उपयोग किए जाते हैं, और आपके पास केवल 4 तत्व हैं। सूचकांक 90 में सरणी में स्थिति 90 है, उदाहरण के लिए - लगभग सभी कोशिकाएं खाली हैं। यदि आपकी सरणी तो आप इसे इंडेक्स करते हैं = "xcnvb" के लिए आपका डेटाH a ( h ( " x c n v b " ) ) = H [ a [ 90 ]HaHa(h("xcnvb"))=Ha[90]
Evil

हैश फ़ंक्शन सरणी में अनुक्रमणिका वापस नहीं करता है। इसके बजाय, यह एक अनुमानित संख्या देता है जिसे सरणी में मैप किया जा सकता है। यह आमतौर पर अन्य ऑपरेटर के रूप में हैश टेबल बाल्टी की संख्या के साथ मापांक ऑपरेटर का उपयोग किया जाता है ।
क्रिस्टोफर शुल्त्स

3

डेविड रिचेर्बी के जवाब पर विस्तार करने के लिए, " हैश फ़ंक्शन " शब्द थोड़ा अतिभारित है। अक्सर, जब हम एक हैश फ़ंक्शन के बारे में बात करते हैं, तो हम एमडी 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जो और भी तेज है, लेकिन पढ़ने में थोड़ा कठिन है। हालाँकि, यह इंडेक्स लुकअप के लिए समान सामान्य सिद्धांत का उपयोग करता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.