क्या तुच्छ कुंजी के मामले में unordered_map पर मानचित्र का उपयोग करने का कोई फायदा है?


371

unordered_mapC ++ के बारे में हाल ही में एक बात ने मुझे एहसास दिलाया कि मुझे unordered_mapज्यादातर मामलों में उपयोग करना चाहिए जहां मैंने mapपहले इस्तेमाल किया था, क्योंकि लुकअप की दक्षता ( amortized O (1) बनाम O (लॉग एन) )। ज्यादातर बार मैं एक मानचित्र का उपयोग करता हूं, मैं intया तो std::stringमुख्य प्रकार का उपयोग करता हूं ; इसलिए, मुझे हैश फ़ंक्शन की परिभाषा से कोई समस्या नहीं है। जितना मैंने इसके बारे में सोचा था, उतना ही मुझे एहसास हुआ कि मैं साधारण प्रकार के साथ चाबियाँ के मामले में एक std::mapसे अधिक उपयोग करने का कोई कारण नहीं पा सकता std::unordered_mapहूं - मैंने इंटरफेस पर एक नज़र डाली, और कोई भी नहीं पाया महत्वपूर्ण अंतर जो मेरे कोड को प्रभावित करेगा।

इसलिए सवाल: क्या उपयोग करने के लिए किसी भी असली कारण है std::mapसे अधिक std::unordered_mapकी तरह साधारण प्रकार के मामले में intऔर std::string?

मैं कड़ाई से प्रोग्रामिंग के दृष्टिकोण से पूछ रहा हूं - मुझे पता है कि यह पूरी तरह से मानक नहीं माना जाता है, और यह पोर्टिंग के साथ समस्याओं का सामना कर सकता है।

इसके अलावा, मुझे उम्मीद है कि एक सही जवाब "डेटा के छोटे सेट के लिए अधिक कुशल हो सकता है " क्योंकि एक छोटे से ओवरहेड (क्या यह सच है?) - इसलिए मैं उन मामलों पर सवाल सीमित करना चाहूंगा जहां राशि है? चाबियाँ गैर-तुच्छ हैं (> 1 024)।

संपादित करें: duh, मैं स्पष्ट (धन्यवाद GMan!) भूल गया - हाँ, नक्शे निश्चित रूप से ऑर्डर किए गए हैं - मुझे पता है कि, और अन्य कारणों की तलाश कर रहा हूं।


22
मुझे साक्षात्कार में यह सवाल पूछना पसंद है: "बबल-सॉर्ट की तुलना में क्विक-सॉर्ट कब बेहतर है?" प्रश्न का उत्तर जटिलता सिद्धांत के व्यावहारिक अनुप्रयोग में अंतर्दृष्टि प्रदान करता है और न केवल सादे काले और सफेद कथन जैसे कि O (1) O (n) या O (k) O (logn) आदि के बराबर है। ..

42
@ ओह, मुझे लगता है कि आपका मतलब है "जब बबल-सॉर्ट जल्दी-से-बेहतर होता है": पी
कोर्नेल किसेल्विकेज

2
क्या स्मार्ट पॉइंटर एक तुच्छ कुंजी होगी?
थोमथोम

यहाँ उन मामलों में से एक है जिसमें नक्शा लाभप्रद है: stackoverflow.com/questions/51964419/…
anilbey

जवाबों:


398

मत भूलो कि mapअपने तत्वों का आदेश दिया है। यदि आप ऐसा नहीं कर सकते, तो जाहिर है आप उपयोग नहीं कर सकते unordered_map

ध्यान रखने योग्य कुछ और बात यह है कि unordered_mapआम तौर पर अधिक मेमोरी का उपयोग किया जाता है । mapबस कुछ हाउस-कीपिंग पॉइंटर्स और प्रत्येक ऑब्जेक्ट के लिए मेमोरी है। इसके विपरीत, unordered_mapएक बड़ा सरणी है (ये कुछ कार्यान्वयन में काफी बड़ा हो सकता है), और फिर प्रत्येक ऑब्जेक्ट के लिए अतिरिक्त मेमोरी। यदि आपको स्मृति-जागरूक होने की आवश्यकता है, तो mapबेहतर साबित होना चाहिए, क्योंकि इसमें बड़े सरणी का अभाव है।

इसलिए, यदि आपको शुद्ध लुक-रिट्रीवल की आवश्यकता है, तो मैं कहूंगा कि unordered_mapजाने का रास्ता है। लेकिन हमेशा ट्रेड-ऑफ होते हैं, और यदि आप उन्हें बर्दाश्त नहीं कर सकते हैं, तो आप इसका उपयोग नहीं कर सकते।

बस व्यक्तिगत अनुभव से, मुझे मुख्य इकाई लुक-अप तालिका के unordered_mapबजाय उपयोग करते समय प्रदर्शन (मापा, निश्चित रूप से) में भारी सुधार मिला map

दूसरी ओर, मैंने पाया कि तत्वों को बार-बार डालने और हटाने में यह बहुत धीमा था। यह तत्वों के एक अपेक्षाकृत स्थिर संग्रह के लिए बहुत अच्छा है, लेकिन अगर आप टन सम्मिलित कर रहे हैं और विलोपन हैशिंग + बकेटिंग जोड़ रहे हैं। (ध्यान दें, यह कई पुनरावृत्तियों पर था।)


3
Unordered_map बनाम मैप (या वेक्टर बनाम सूची) की बड़ी (r) मेमोरी ब्लॉक संपत्ति के बारे में एक और बात, डिफ़ॉल्ट प्रक्रिया ढेर (यहां विंडोज पर बात करना) क्रमबद्ध है। एक मल्टीथ्रेडेड एप्लिकेशन में बड़ी मात्रा में आवंटन (छोटे) ब्लॉक बहुत महंगा है।
ROAR

4
आरए: आप कुछ हद तक नियंत्रित कर सकते हैं कि आपके खुद के आवंटनकर्ता किसी भी कंटेनर के साथ संयुक्त हो, अगर आपको लगता है कि यह किसी विशेष कार्यक्रम के लिए मायने रखता है।

9
यदि आप के आकार को जानते हैं unordered_mapऔर शुरू में आरक्षित करते हैं - तो क्या आप अभी भी कई सम्मिलन का दंड देते हैं? कहो, आप केवल एक बार सम्मिलित कर रहे हैं जब आपने लुकअप तालिका बनाई थी - और फिर बाद में केवल इसे पढ़ा।
थोमथोम

3
@thomthom जहां तक ​​मैं बता सकता हूं, प्रदर्शन के मामले में कोई जुर्माना नहीं होना चाहिए। कारण प्रदर्शन हिट होता है, इस तथ्य के कारण है कि यदि सरणी बहुत बड़ी हो जाती है, तो यह सभी तत्वों का पुन: परीक्षण करेगा। आप आरक्षित कॉल करते हैं, यह संभावित रूप से मौजूदा तत्वों मिला देना होगा, लेकिन यदि आप शुरू में इसे कहते हैं, तो कोई जुर्माना नहीं लगाया जाएगा, कम से कम के अनुसार cplusplus.com/reference/unordered_map/unordered_map/reserve
रिचर्ड फंग

6
मुझे पूरा यकीन है कि मेमोरी-वार यह विपरीत है। एक अनियंत्रित कंटेनर के लिए डिफ़ॉल्ट 1.0 लोड कारक मानते हुए: आपके पास बाल्टी के लिए प्रति तत्व एक पॉइंटर और अगले-इन-इन-बाल्टी के लिए प्रति तत्व एक पॉइंटर है, इसलिए आप प्रत्येक तत्व के साथ दो पॉइंटर्स प्लस डेटा के साथ समाप्त होते हैं। एक ऑर्डर किए गए कंटेनर के लिए, दूसरी ओर, एक विशिष्ट आरबी-ट्री कार्यान्वयन में होगा: तीन पॉइंटर्स (बाएं / दाएं / माता-पिता) प्लस एक रंग बिट जो संरेखण के कारण एक शब्द लेता है। यह प्रत्येक तत्व के साथ चार पॉइंटर्स प्लस डेटा है।
याकोव गल्का सेप

126

यदि आप अपने std::mapऔर std::unordered_mapकार्यान्वयन की गति की तुलना करना चाहते हैं , तो आप Google के स्पार्श प्रोजेक्ट का उपयोग कर सकते हैं, जिनके पास time_hash_map प्रोग्राम है। उदाहरण के लिए, x86_64 लिनक्स सिस्टम पर gcc 4.4.2 के साथ

$ ./time_hash_map
TR1 UNORDERED_MAP (4 byte objects, 10000000 iterations):
map_grow              126.1 ns  (27427396 hashes, 40000000 copies)  290.9 MB
map_predict/grow       67.4 ns  (10000000 hashes, 40000000 copies)  232.8 MB
map_replace            22.3 ns  (37427396 hashes, 40000000 copies)
map_fetch              16.3 ns  (37427396 hashes, 40000000 copies)
map_fetch_empty         9.8 ns  (10000000 hashes,        0 copies)
map_remove             49.1 ns  (37427396 hashes, 40000000 copies)
map_toggle             86.1 ns  (20000000 hashes, 40000000 copies)

STANDARD MAP (4 byte objects, 10000000 iterations):
map_grow              225.3 ns  (       0 hashes, 20000000 copies)  462.4 MB
map_predict/grow      225.1 ns  (       0 hashes, 20000000 copies)  462.6 MB
map_replace           151.2 ns  (       0 hashes, 20000000 copies)
map_fetch             156.0 ns  (       0 hashes, 20000000 copies)
map_fetch_empty         1.4 ns  (       0 hashes,        0 copies)
map_remove            141.0 ns  (       0 hashes, 20000000 copies)
map_toggle             67.3 ns  (       0 hashes, 20000000 copies)

2
ऐसा लगता है कि unordered मैप ज्यादातर ऑपरेशंस पर मैप को बीट करता है। इंसर्शन पर अमल करें ...
Michael IV

7
विरलता अब मौजूद नहीं है। इसे हटा दिया गया है या नीचे ले जाया गया है।
User9102d82 20

1
@ User9102d82 मैंने प्रश्न को वेकबैकमैच लिंक से संदर्भित किया है ।
और्री

बस यह सुनिश्चित करने के लिए कि अन्य समय के अलावा अन्य संख्याओं को भी नोटिस करते हैं: उन परीक्षणों को 4 बाइट ऑब्जेक्ट्स / डेटास्ट्रक्चर उर्फ ​​इंट के साथ किया गया था। यदि आप किसी ऐसी चीज को स्टोर करते हैं जिसके लिए हैशिंग हैशिंग या बड़ा है (कॉपी ऑपरेशंस को भारी बना रहा है), तो मानक मानचित्र में जल्दी फायदा हो सकता है!
एलेक्सगॉर्ग

82

मैं लगभग उसी बिंदु को गूँजता हूँ जो जीएमन ने बनाया था: उपयोग के प्रकार पर निर्भर करता है, std::map(और अक्सर हो सकता है) std::tr1::unordered_mapवीएस 2008 SP1 में शामिल कार्यान्वयन की तुलना में तेज़ी से हो सकता है ।

ध्यान में रखने के लिए कुछ जटिल कारक हैं। उदाहरण के लिए, में std::map, आप कुंजियों की तुलना कर रहे हैं, जिसका अर्थ है कि आप केवल पेड़ की दाईं और बाईं उप-शाखाओं के बीच अंतर करने के लिए कुंजी की शुरुआत में पर्याप्त रूप से देखते हैं। मेरे अनुभव में, लगभग एक ही समय में आप एक संपूर्ण कुंजी को देखते हैं, यदि आप int जैसी किसी चीज़ का उपयोग कर रहे हैं, जिसकी आप एकल निर्देश में तुलना कर सकते हैं। अधिक विशिष्ट कुंजी प्रकार जैसे std :: string के साथ, आप अक्सर केवल कुछ वर्णों की तुलना करते हैं।

एक सभ्य हैश फ़ंक्शन, इसके विपरीत, हमेशा पूरी कुंजी को देखता है । IOW, भले ही टेबल लुकअप निरंतर जटिलता है, हैश में ही लगभग रैखिक जटिलता है (हालांकि कुंजी की लंबाई पर, आइटम की संख्या नहीं)। कुंजी के रूप में लंबे समय के तार के साथ, std::mapएक खोज को समाप्त करने से पहले एक खोज unordered_mapभी शुरू हो सकती है ।

दूसरा, जबकि वहाँ हैश तालिकाओं का आकार बदलने के कई तरीके हैं, उनमें से ज्यादातर बहुत धीमी गति से कर रहे हैं - का कहना है कि जब तक लुकअप हैं काफी सम्मिलन और विलोपन से अधिक लगातार, std :: नक्शा अक्सर तेजी से हो जाएगा std::unordered_map

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

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


2
हैश का आकार बदलना dynamic hashingटेकनीक द्वारा कम किया जा सकता है , जिसमें संक्रमण काल ​​होता है, जिसमें हर बार जब आप एक आइटम डालते हैं, तो आप kअन्य आइटमों को भी पुनः साझा करते हैं। बेशक, इसका मतलब है कि संक्रमण के दौरान आपको 2 अलग-अलग तालिकाओं को खोजना होगा ...
मैथ्यू एम।

2
"कुंजी के रूप में लंबे समय तक तार के साथ, एक std :: नक्शा एक खोज को समाप्त कर सकता है इससे पहले कि एक unordered_map भी अपनी खोज शुरू कर दे।" - यदि कुंजी संग्रह में मौजूद नहीं है। यदि यह मौजूद है, तो निश्चित रूप से मैच की पुष्टि करने के लिए पूरी लंबाई की आवश्यकता है। लेकिन इसी तरह unordered_mapएक हैश मैच की पूरी तुलना के साथ पुष्टि करने की जरूरत है, इसलिए यह सब निर्भर करता है कि आप जिस लुकअप प्रक्रिया के विपरीत हैं, उसके कौन से हिस्से हैं।
स्टीव जेसोप

2
आप आमतौर पर डेटा के ज्ञान के आधार पर हैश फ़ंक्शन को बदल सकते हैं। उदाहरण के लिए, यदि आपके लंबे तार पिछले 20 बाइट्स में पहले 100 की तुलना में अधिक भिन्न हैं, तो अंतिम 20 में हैश।
एरिक एरोनिटी

56

मैं @ जेरी कॉफ़िन के उत्तर से अंतर्द्वंद्व था, जिसने सुझाव दिया कि कुछ प्रयोग (जिसे पास्टबिन से डाउनलोड किया जा सकता है ) के बाद आदेशित नक्शा प्रदर्शन को बढ़ाता है, लंबे स्ट्रिंग्स पर प्रदर्शित होता है , मैंने पाया है कि यह केवल संग्रह के लिए सही लगता है यादृच्छिक स्ट्रिंग्स के साथ, जब मानचित्र को एक क्रमबद्ध शब्दकोश (जिसमें उपसर्ग-ओवरलैप की काफी मात्रा के साथ शब्द होते हैं) के साथ आरंभीकृत किया जाता है, यह नियम टूट जाता है, संभवत: मूल्य को पुनः प्राप्त करने के लिए आवश्यक वृक्ष की गहराई में वृद्धि के कारण। परिणाम नीचे दिखाए गए हैं, 1 नंबर कॉलम डालने का समय है, दूसरा लाने का समय है।

g++ -g -O3 --std=c++0x   -c -o stdtests.o stdtests.cpp
g++ -o stdtests stdtests.o
gmurphy@interloper:HashTests$ ./stdtests
# 1st number column is insert time, 2nd is fetch time
 ** Integer Keys ** 
 unordered:      137      15
   ordered:      168      81
 ** Random String Keys ** 
 unordered:       55      50
   ordered:       33      31
 ** Real Words Keys ** 
 unordered:      278      76
   ordered:      516     298

2
परीक्षण के लिए धन्यवाद। यह सुनिश्चित करने के लिए कि हम शोर को माप नहीं रहे हैं मैंने इसे प्रत्येक ऑपरेशन को कई बार करने के लिए बदल दिया (और नक्शे में 1 के बजाय काउंटर डाला)। मैंने इसे विभिन्न प्रकार की कुंजियों (2 से 1000 तक) और मानचित्र में ~ 100 कुंजियों तक, std::mapआमतौर पर आउटपरफॉर्म std::unordered_map, विशेषकर पूर्णांक कुंजियों के लिए चलाया , लेकिन ~ 100 कुंजियाँ ऐसा लगता है कि यह अपनी बढ़त खो देती है और std::unordered_mapजीतने लगती है। पहले से ही ऑर्डर किए गए अनुक्रम को एक std::mapबहुत बुरे में सम्मिलित करते हुए , आपको इसकी सबसे खराब स्थिति (O (N)) मिलेगी।
एंड्रियास मैग्यूसन

30

मैं सिर्फ यह बताना चाहूंगा कि ... कई तरह के हैं unordered_map

ऊपर देखो विकिपीडिया लेख हैश नक्शे पर। किस कार्यान्वयन के आधार पर, लुक-अप, प्रविष्टि और विलोपन की विशेषताओं में काफी भिन्नता हो सकती है।

और यही वह है जो मुझे unordered_mapएसटीएल के अलावा के साथ सबसे अधिक चिंतित करता है : उन्हें एक विशेष कार्यान्वयन का चयन करना होगा क्योंकि मुझे संदेह है कि वे Policyसड़क से नीचे जाएंगे , और इसलिए हम औसत उपयोग के लिए कार्यान्वयन के साथ फंस जाएंगे और इसके लिए कुछ भी नहीं होगा अन्य मामले ...

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

एक और उदाहरण: कुछ हैश मानचित्र एक बाल्टी के लिए नोड्स की एक सरल सूची का उपयोग करते हैं, अन्य एक मानचित्र का उपयोग करते हैं, अन्य नोड्स का उपयोग नहीं करते हैं लेकिन निकटतम स्लॉट ढूंढते हैं और अंत में कुछ नोड्स की सूची का उपयोग करेंगे लेकिन इसे फिर से व्यवस्थित करें ताकि अंतिम एक्सेस किया गया तत्व सामने है (कैशिंग की तरह)।

तो इस समय मैं std::mapया loki::AssocVector( शायद जमे हुए डेटा सेट के लिए) को प्राथमिकता देता हूं ।

मुझे गलत मत समझो, मैं std::unordered_mapभविष्य में इसका उपयोग करना चाहूंगा और कर सकता हूं, लेकिन ऐसे कंटेनर के पोर्टेबिलिटी पर "विश्वास" करना मुश्किल है, जब आप इसे लागू करने के सभी तरीकों और परिणाम के विभिन्न प्रदर्शनों के बारे में सोचते हैं इस का।


17
+1: वैध बिंदु - जीवन तब आसान था जब मैं अपने स्वयं के कार्यान्वयन का उपयोग कर रहा था - कम से कम मुझे पता था कि यह कहाँ चूसा है:>
Kornel Kisielewicz

25

महत्वपूर्ण अंतर जो वास्तव में यहां पर्याप्त रूप से उल्लेख नहीं किया गया है:

  • mapसभी तत्वों के लिए पुनरावृत्तियों को स्थिर रखता है, C ++ 17 में आप mapपुनरावृत्तियों को अमान्य किए बिना भी तत्वों को एक से दूसरे तक ले जा सकते हैं (और यदि किसी संभावित आवंटन के बिना ठीक से लागू किया गया है)।
  • map एकल संचालन के लिए समय आमतौर पर अधिक सुसंगत होते हैं क्योंकि उन्हें कभी बड़े आवंटन की आवश्यकता नहीं होती है।
  • unordered_mapstd::hashlibstdc ++ में कार्यान्वित के रूप में उपयोग करना DoS के लिए असुरक्षित है अगर अविश्वासित इनपुट के साथ खिलाया जाता है (यह एक निरंतर बीज के साथ मुरमुरैश 2 का उपयोग करता है - ऐसा नहीं है कि बोने से वास्तव में मदद मिलेगी, https://emboss.github.io/blog/2012/12/14/14 देखें ब्रेकिंग-मुरमुर-हैश-बाढ़-डॉस-रीलोडेड / )।
  • आदेश दिया जा रहा है कुशल रेंज खोजों को सक्षम करता है, जैसे कि key 42 के साथ सभी तत्वों पर पुनरावृति।

14

हैश टेबल में सामान्य मानचित्र कार्यान्वयन की तुलना में उच्च स्थिरांक होते हैं, जो छोटे कंटेनरों के लिए महत्वपूर्ण हो जाते हैं। अधिकतम आकार 10, 100 या शायद 1,000 या अधिक है? कॉन्स्टेंट हमेशा की तरह ही हैं, लेकिन O (log n) O (k) के करीब है। (याद रखें कि लघुगणकीय जटिलता अभी भी वास्तव में अच्छी है।)

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

इस तरह से आपको अन्य (आमतौर पर यूडीटी) प्रकारों के लिए हैश फ़ंक्शन लिखने के बारे में सोचना भी नहीं पड़ता है, और बस ऑप <(जो आप वैसे भी चाहते हैं) लिखें।


@ रॉगर, क्या आप उन तत्वों की अनुमानित राशि जानते हैं जिन पर unordered_map सबसे अच्छा मैप करता है? मैं शायद इसके लिए एक परीक्षण लिखूंगा, वैसे भी ... (+1)
कोर्नेल किसेल्विकेज़

1
@ कोर्नेल: यह बहुत अधिक नहीं लेता है; मेरे परीक्षण लगभग 10,000 तत्वों के साथ थे। यदि हम वास्तव में सटीक ग्राफ़ चाहते हैं , तो आप कुछ प्लेटफ़ॉर्म और निश्चित कैश आकार के साथ mapऔर उनमें से एक के कार्यान्वयन को देख सकते हैं unordered_map, और एक जटिल विश्लेषण कर सकते हैं। : पी
GManNickG

कार्यान्वयन विवरणों पर निर्भर करता है, संकलन-समय ट्यूनिंग पैरामीटर (यदि आप अपना स्वयं का कार्यान्वयन लिख रहे हैं, तो समर्थन करना आसान है), और यहां तक ​​कि परीक्षणों के लिए उपयोग की जाने वाली विशिष्ट मशीन भी। अन्य कंटेनरों की तरह, समिति केवल व्यापक आवश्यकताओं को निर्धारित करती है।

13

अन्य उत्तरों में कारण दिए गए हैं; यहाँ एक और है।

std :: मैप (संतुलित बाइनरी ट्री) ऑपरेशंस O (लॉग एन) और सबसे खराब स्थिति O (लॉग एन) amortized हैं। std :: unordered_map (हैश टेबल) परिचालनों को O (1) और सबसे खराब स्थिति O (n) को परिचालित किया जाता है।

यह कैसे व्यवहार में है कि हैश तालिका "हिचकी" हर एक बार एक ओ (एन) ऑपरेशन के साथ होती है, जो आपके आवेदन को सहन कर सकती है या नहीं हो सकती है। यदि यह इसे बर्दाश्त नहीं कर सकता है, तो आप std :: map over std :: unordered_map पसंद करेंगे।


12

सारांश

आदेश देना महत्वपूर्ण नहीं है:

  • यदि आप एक बार बड़ी तालिका बनाने जा रहे हैं और बहुत सारी क्वेरीज़ का उपयोग करते हैं std::unordered_map
  • यदि आप छोटी तालिका बनाने जा रहे हैं (100 तत्वों के अंतर्गत हो सकता है) और बहुत सारी क्वेरी करें, उपयोग करें std::map। ऐसा इसलिए है क्योंकि इस पर लिखा है O(log n)
  • अगर आप टेबल को काफी बदलने जा रहे हैं तो यह अच्छा विकल्प हो सकता std::map है।
  • यदि आप संदेह में हैं, तो बस उपयोग करें std::unordered_map

ऐतिहासिक संदर्भ

ज्यादातर भाषाओं में, अनअॉर्डरेटेड मैप (उर्फ हैश बेस्ड डिक्शनरी) डिफॉल्ट मैप होता है, लेकिन C ++ में आपको डिफॉल्ट मैप के रूप में ऑर्डर किया हुआ मैप मिलता है। ये कैसे हो गया? कुछ लोग ग़लती से मान लेते हैं कि C ++ कमेटी ने यह निर्णय अपने अनूठे ज्ञान में लिया था, लेकिन सच्चाई दुर्भाग्य से इससे अधिक बदसूरत है।

यह व्यापक रूप से माना जाता है कि सी ++ आदेशित नक्शे के साथ डिफ़ॉल्ट रूप से समाप्त हो गया है क्योंकि उन्हें लागू करने के तरीके पर बहुत अधिक पैरामीटर नहीं हैं। दूसरी ओर, हैश आधारित कार्यान्वयन के बारे में बात करने के लिए टन है। इसलिए मानकीकरण में ग्रिडलॉक से बचने के लिए उन्हें सिर्फ ऑर्डर किए गए नक्शे के साथ मिला । 2005 के आसपास, कई भाषाओं में पहले से ही हैश आधारित कार्यान्वयन के अच्छे कार्यान्वयन थे और इसलिए समिति के लिए नए को स्वीकार करना अधिक आसान था std::unordered_map। एक आदर्श दुनिया में, std::mapअनियंत्रित होता और हम std::ordered_mapअलग प्रकार के होते।

प्रदर्शन

नीचे दो रेखांकन खुद के लिए बोलना चाहिए ( स्रोत ):

यहां छवि विवरण दर्ज करें

यहां छवि विवरण दर्ज करें


दिलचस्प डेटा; आपने अपने परीक्षणों में कितने प्लेटफ़ॉर्म शामिल किए?
टोबी स्पाईट

1
जब std :: unordered_map हमेशा std की तुलना में बेहतर प्रदर्शन करता है, तब छोटी तालिका के लिए मैप का उपयोग करना चाहिए: unordered_map आपके द्वारा यहां पोस्ट की गई 2 छवियों के अनुसार है?
रिकी

ग्राफ़ 0.13M या अधिक तत्वों के लिए प्रदर्शन दिखाता है। यदि आपके पास छोटे (<100) तत्व हो सकते हैं तो O (लॉग एन) अनऑर्डर किए गए नक्शे से छोटा हो सकता है।
शीतल शाह

10

मैंने हाल ही में एक परीक्षण किया है जो 50000 मर्ज और सॉर्ट करता है। इसका मतलब है कि अगर स्ट्रिंग कीज़ समान हैं, तो बाइट स्ट्रिंग को मर्ज करें। और अंतिम आउटपुट को सॉर्ट किया जाना चाहिए। इसलिए इसमें हर प्रविष्टि के लिए एक नज़र शामिल है।

के लिए mapकार्यान्वयन, यह काम खत्म करने के लिए 200 एमएस लेता है। के लिए unordered_map+ map, इसके लिए 70 एमएस लेता unordered_mapप्रविष्टि और के लिए 80 एमएस mapप्रविष्टि। इसलिए हाइब्रिड कार्यान्वयन 50 एमएस तेज है।

हमें इसका उपयोग करने से पहले दो बार सोचना चाहिए map। यदि आपको केवल अपने कार्यक्रम के अंतिम परिणाम में डेटा को सॉर्ट करने की आवश्यकता है, तो एक हाइब्रिड समाधान बेहतर हो सकता है।


0

उपरोक्त सभी के लिए छोटा जोड़:

बेहतर उपयोग map, जब आपको तत्वों को सीमा से प्राप्त करने की आवश्यकता होती है, क्योंकि वे क्रमबद्ध होते हैं और आप बस एक सीमा से दूसरी सीमा तक उन पर पुनरावृति कर सकते हैं।


-1

प्रेषक: http://www.cplusplus.com/reference/map/map/

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

मानचित्र कंटेनर आम तौर पर अपनी कुंजी द्वारा व्यक्तिगत तत्वों का उपयोग करने के लिए unordered_map कंटेनरों की तुलना में धीमा होते हैं, लेकिन वे अपने आदेश के आधार पर सबसेट पर प्रत्यक्ष पुनरावृत्ति की अनुमति देते हैं। "

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