हैश टेबल बनाम बाइनरी पेड़


30

शब्दकोश को लागू करते समय ('मैं अपने ग्राहक आईडी द्वारा ग्राहक डेटा देखना चाहता हूं'), उपयोग की जाने वाली विशिष्ट डेटा संरचनाएं हैश टेबल और बाइनरी सर्च ट्री हैं। मैं उदाहरण के लिए जानता हूं कि सी ++ एसटीएल पुस्तकालय शब्दकोशों (वे उन्हें नक्शे कहते हैं) का उपयोग करके (संतुलित) द्विआधारी खोज पेड़ों का उपयोग करते हैं, और .NET फ्रेमवर्क हुड के नीचे हैश तालिकाओं का उपयोग करता है।

इन डेटा संरचनाओं के फायदे और नुकसान क्या हैं? क्या कुछ अन्य विकल्प हैं जो कुछ स्थितियों में उचित हैं?

ध्यान दें कि मैं उन मामलों में विशेष रूप से दिलचस्पी नहीं रखता हूं जहां चाबियाँ एक मजबूत अंतर्निहित संरचना हैं, कहते हैं, वे सभी 1 और n या कुछ के बीच पूर्णांक हैं।


1
मैं आपको अतिरंजित कर दूंगा लेकिन आप केवल "1 और n के बीच पूर्णांक" नहीं कह सकते क्योंकि उस मामले में एक सरणी अन्य सभी डेटा संरचनाओं से आगे निकल जाएगी :-)। "स्ट्रिंग्स" उचित लगता है और अधिकांश स्थितियों को कवर करता है।
jamm

@ जैमद ने कहा कि वह उस मामले में कोई दिलचस्पी नहीं है
जो

@ जो मुझे लगा कि यह स्पष्ट है मैंने इसे ध्यान में रखा। वैसे भी यह कुंजी का सबसे खराब संभव उदाहरण देने का एक कारण नहीं है।
जम्म

1
वास्तव में .NET में हैश टेबल का उपयोग करके कार्यान्वित पेड़ों और शब्दकोशों दोनों में शब्दकोशों है (और 2011 मानक के बाद से C ++)।
sepp2k

SO पर समान संभव: stackoverflow.com/questions/371136/…
Ciro Santilli 新疆:::

जवाबों:


26

इस विषय पर एक संपूर्ण ग्रंथ लिखा जा सकता है; मैं सिर्फ कुछ मुख्य बिंदुओं को कवर करने जा रहा हूं, और मैं अन्य डेटा संरचनाओं की चर्चा न्यूनतम रखूंगा (वास्तव में कई संस्करण हैं)। इस उत्तर के दौरान, शब्दकोश में कुंजियों की संख्या है।n

संक्षिप्त उत्तर यह है कि हैश टेबल ज्यादातर मामलों में तेज होते हैं , लेकिन उनकी सबसे खराब स्थिति में बहुत खराब हो सकते हैं। खोज के पेड़ के कई फायदे हैं, जिसमें सबसे खराब स्थिति वाला व्यवहार भी शामिल है , लेकिन विशिष्ट मामलों में कुछ धीमा है।

संतुलित द्विआधारी खोज पेड़ों में एक समान रूप से जटिलता होती है: प्रत्येक तत्व पेड़ में एक नोड (आमतौर पर स्मृति के 4 शब्द) लेता है, और मूल संचालन (लुकअप, प्रविष्टि, विलोपन) समय लेता है (गारंटी asymptotic ऊपरी बाध्य)। अधिक सटीक रूप से, पेड़ में एक पहुंच के बारे में तुलना होती है।हे(एलजी(n))एलजी2(n)

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

हैश टेबल के साथ एक सामान्य समस्या यह है कि जटिलता की गारंटी नहीं है।हे(1)

  • इसके अलावा, एक बिंदु है जहां तालिका पूर्ण हो जाती है; जब ऐसा होता है (या, बेहतर, उससे थोड़ा पहले), तालिका को बड़ा करने की आवश्यकता होती है, जिसे लागत के लिए अपने सभी तत्वों को स्थानांतरित करने की आवश्यकता होती है । जब बहुत सारे तत्व जोड़े जाते हैं तो यह "झटकेदार" व्यवहार का परिचय दे सकता है।हे(n)
  • इनपुट के लिए कुछ हैश मानों से टकराना संभव है। यह शायद ही कभी स्वाभाविक रूप से होता है, लेकिन यह एक सुरक्षा समस्या हो सकती है यदि इनपुट को एक हमलावर द्वारा चुना जाता है: यह कुछ सर्वरों को काफी धीमा करने का एक तरीका है। इस समस्या ने कुछ प्रोग्रामिंग लैंग्वेज इम्प्लीमेंटेशन (जैसे पर्ल और पायथन) को एक पुरानी पुरानी हैश टेबल से एक हैश फ़ंक्शन में बदलने के लिए एक यादृच्छिक संख्या को चुना है, जिसमें हैश टेबल बनाया गया है, एक साथ हैश फ़ंक्शन के साथ स्विच किया गया है, जो इस यादृच्छिक गति को अच्छी तरह से फैलाता है। (जो में गुणक स्थिरांक को बढ़ाता है ), या बाइनरी सर्च ट्री को। हालांकि आप क्रिप्टोग्राफ़िक हैश का उपयोग करके टकराव से बच सकते हैं, यह व्यवहार में नहीं किया जाता है क्योंकि क्रिप्टोग्राफ़िक हैश तुलना करने के लिए तुलनात्मक रूप से बहुत धीमा है।हे(1)

जब आप डेटा स्थानीयता को मिक्स में फेंकते हैं , हैश टेबल खराब करते हैं। वे ठीक से काम करते हैं क्योंकि वे संबंधित तत्वों को दूर तक संग्रहीत करते हैं, जिसका अर्थ है कि यदि आवेदन अनुक्रम में उपसर्ग साझा करने वाले तत्वों को देखता है, तो यह कैश प्रभाव से लाभ नहीं होगा। यह प्रासंगिक नहीं है यदि आवेदन अनिवार्य रूप से यादृच्छिक रूप से दिखता है।

खोज पेड़ों के पक्ष में एक अन्य कारक यह है कि वे एक अपरिवर्तनीय डेटा संरचना हैं: यदि आपको किसी पेड़ की प्रति लेने और उसमें कुछ तत्वों को बदलने की आवश्यकता है, तो आप अधिकांश डेटा संरचना साझा कर सकते हैं। यदि आप एक हैश तालिका की एक प्रति लेते हैं, तो आपको पूरे व्यू पॉइंट को कॉपी करने की आवश्यकता है। इसके अलावा, यदि आप विशुद्ध रूप से कार्यात्मक भाषाओं में काम कर रहे हैं, तो हैश टेबल अक्सर एक विकल्प नहीं होते हैं।

जब आप स्ट्रिंग्स से परे जाते हैं, तो हैश टेबल और बाइनरी सर्च ट्री, कुंजी के डेटा प्रकार पर अलग-अलग आवश्यकताएं बनाते हैं: हैश टेबल को एक हैश फ़ंक्शन (कुंजी से एक फ़ंक्शन की आवश्यकता होती है जैसे कि , जबकि बाइनरी सर्च कुल ऑर्डर की आवश्यकता होती है। यदि डेटा संग्रहीत करने के लिए पर्याप्त जगह होती है, तो को कभी-कभी कैश किया जा सकता है, जहाँ कुंजी संग्रहीत होती है; तुलनाओं का परिणाम कैशिंग (एक बाइनरी ऑपरेशन) अक्सर अव्यवहारिक होता है। दूसरी ओर, तुलना शॉर्टकटिंग से लाभ उठा सकती है: यदि कुंजी अक्सर पहले कुछ बाइट्स के भीतर भिन्न होती है, तो एक नकारात्मक तुलना बहुत तेज हो सकती है।कश्मीर1कश्मीर2(कश्मीर1)=(कश्मीर2)

विशेष रूप से, यदि आपको कुंजियों पर आदेश की आवश्यकता है , उदाहरण के लिए यदि आप वर्णमाला क्रम में कुंजियों को सूचीबद्ध करने में सक्षम होना चाहते हैं, तो हैश टेबल कोई मदद नहीं है (आपको उन्हें क्रमबद्ध करने की आवश्यकता होगी), जबकि आप क्रम में एक खोज ट्री को सीधा कर सकते हैं।

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

जब चाबियाँ तार (या पूर्णांक) होती हैं, तो एक त्रिकोणीय दूसरा विकल्प हो सकता है। एक ट्री एक पेड़ है, लेकिन एक खोज ट्री से अलग-अलग अनुक्रमित किया जाता है: आप बाइनरी में कुंजी लिखते हैं, और 0 के लिए बाएं जाते हैं और 1 के लिए दाएं। पहुंच की लागत इस प्रकार कुंजी की लंबाई के लिए आनुपातिक है। मध्यवर्ती नोड्स को हटाने के लिए कोशिश की जा सकती है; इसे पेट्रीसिया ट्राइ या रेडिक्स ट्री के रूप में जाना जाता है । मूलांक के पेड़ संतुलित पेड़ों को उखाड़ सकते हैं, खासकर जब कई चाबियाँ एक आम उपसर्ग साझा करती हैं।


2
क्या BST में भी डेटा स्थान खराब नहीं है?
स्विक

@svick नोड्स कैसे आवंटित किए जाते हैं, इस पर निर्भर करता है या नहीं। पेड़ की शुष्कता को बढ़ाने से चल रहे समय (लागत बड़ी और अधिक जटिल कोड) से समझौता किए बिना मदद मिल सकती है।
गिल्स एसओ- बुराई को रोकें '

2
BST पर तत्वों को "क्रम में" प्राप्त करना आसान है, हैश तालिका के लिए यह प्रश्न से बाहर है।
वॉनब्रांड

सुरक्षा कारणों से इतर, अगर हैश टेबल के खराब होने का समय खराब होता है, तो उनका औसत केस बाइनरी पेड़ों की तुलना में बेहतर क्यों है? मुझे लगता है कि उपयोगिता / उपयोगकर्ता सुविधा का वृक्ष के साथ संबंध खत्म होने में कितना समय लगता है, इसलिए अपेक्षित (औसत) मूल्य यह सब मायने रखता है।
केल्मिक्रा

@ Kyth'Py1k "पेड़ खत्म होने" से आपका क्या मतलब है? हैश टेबल्स की बात यह है कि एक समय में एक मान का उपयोग किया जाए, न कि पूरे पेड़ को, अन्यथा एक सूची या सरणी बेहतर काम करेगी। यहां तक ​​कि उन स्थितियों में भी जहां औसत मूल्य है जो मायने रखता है (जो हमेशा मामला नहीं होता है, उदाहरण के लिए जब आपके पास वास्तविक समय की कमी है), यह उन अनुरोधों पर औसत है जो किसी दिए गए स्थिति में किए जाते हैं, जो अक्सर मेज पर एक समान नहीं होते हैं - जैसे एक निश्चित उपसर्ग के लिए पक्षपाती।
गिलेस एसओ- बुराई को रोकना '22
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.