2012-12-05 35 views
21

मेरे पास एक std :: unordered_map है कि मैं पुनरावृत्ति के माध्यम से तत्वों को हटा दूंगा।तत्वों को हटाते समय मैं std :: unordered_map को पुनः लोड करने से कैसे रोकूं?

auto itr = myMap.begin(); 
while (itr != myMap.end()) { 
    if (/* removal condition */) { 
     itr = myMap.erase(itr); 
    } else { 
     ++itr; 
    } 
} 

मैं किसी भी महंगा ऑपरेशनों को जब तक मैं तत्वों है कि मैं हटाने की जरूरत के सभी को दूर करने के लिए किया कर रहा हूँ के लिए नक्शे को रोकने के लिए चाहते हैं। क्या मेरे पास वैध चिंता है? क्या मैं गलत समझ रहा हूं कि आंतरिक संग्रहण कैसे काम करता है?

उत्तर

7

अव्यवस्थित कंटेनर एक erase दौरान rehashing मनाही है।अनुरोध]/p14:

erase सदस्यों मिट तत्वों को केवल iterators और संदर्भ को अमान्य करेगा, और तत्वों कि मिटाया नहीं कर रहे हैं के रिश्तेदार क्रम बनाए रखने के।

[unord.req]/p9:

rehashing iterators को अमान्य कर, परिवर्तन तत्वों के बीच आदेश देने, और ...

आपका कोड ठीक है है के रूप में।

+0

मुझे पता है कि हम 4 साल बाद इस प्रश्न को देख रहे हैं, लेकिन मुझे यह जवाब देखने में खुशी है कि यह जवाब मिश्रण में प्रवेश करता है। दस्तावेज़ीकरण को फिर से देखकर, यह स्पष्ट है कि सबसे खराब-कास्ट जटिलता संभावित रीहैशिंग से नहीं आती है, बल्कि हैश टकराव से। मुझे लगता है कि यह आधिकारिक तौर पर सही जवाब है। – vmrob

+0

तो तालिका केवल बढ़ सकती है। –

+0

एक अनियंत्रित कंटेनर में बाल्टी की संख्या कभी भी 'मिटा' के तहत घट जाएगी। 'रिहाश' के तहत संख्या को कम करने की अनुमति है, और सभी कार्यान्वयन ऐसा करेंगे। –

5

जहां तक ​​मेरा बता सकते हैं, std::unordered_maperase(itr) पर मिश्रित करने की अनुमति दी है:

सी ++ 11 टेबल 103 - अक्रमित साहचर्य कंटेनर आवश्यकताओं

a.erase(q)

मिटाता तत्व बताया q द्वारा। वापसी मान इटरेटर तुरंत q से पहले मिटाए जाने से पहले है।

औसत मामले O(1), सबसे खराब मामले O(a.size())

इसलिए यह प्रतीत होता है कि आप एक वैध चिंता का विषय है। इसे संबोधित करने के लिए, मैं कई मार्ग सुझा सकता हूं:

  1. सुनिश्चित करें कि यह एक अनुमानित व्यक्ति की बजाय वास्तविक समस्या है। एप्लिकेशन को प्रोफाइल करें, अपने सी ++ लाइब्रेरी के लिए स्रोत कोड देखें, आदि
  2. यदि यह एक वास्तविक समस्या है, तो एक अलग कंटेनर या एक अलग एल्गोरिदम का उपयोग करने पर विचार करें।
  3. प्रत्येक तत्व से जुड़े बूलियन ध्वज के माध्यम से हटाने के लिए तत्वों को चिह्नित करने और समय-समय पर हटाए गए तत्वों को साफ़ करने पर विचार करें, जिससे लागत को कम किया जा सके।
  4. टिप्पणियों में @amit द्वारा सुझाए गए लोड कारक के साथ प्रयोग करने पर विचार करें। हालांकि कंटेनर को अभी भी तत्वों को मिटाने के लिए O(a.size()) समय लेने की अनुमति दी जाएगी, फिर भी एक अलग लोड कारक आपके आवेदन के वास्तविक-विश्व प्रदर्शन पर असर डाल सकता है।
+0

हालांकि जानकारीपूर्ण और संबंधित - यह सवाल का जवाब नहीं देता है: 'तत्वों को हटाने के दौरान मैं std :: unordered_map को पुनः लोड करने से कैसे रोकूं?' – amit

+0

@amit: यदि आप लाइनों के बीच पढ़ते हैं, तो यह करता है (इसका उत्तर सटीक सवाल यह है कि आप नहीं कर सकते :) :) – NPE

+0

सुनिश्चित नहीं है कि आप नहीं कर सकते हैं, आप max_load_factor को एक काल्पनिक उच्च मान पर सेट कर सकते हैं, और इसे बाद में सामान्य आकार में रीसेट कर सकते हैं। मुझे ऐसा कुछ भी नहीं मिला जो दस्तावेज़ों में इसकी पुष्टि करता है (इस प्रकार कोई जवाब पोस्ट नहीं कर रहा है) - लेकिन मुझे संदेह है कि यह आपको रीहैश को नियंत्रित करने में सक्षम होगा और सबसे अधिक 2. – amit

2

मुझे यकीन है कि यह काम करेगा, मैं दस्तावेज में इसके लिए एक पुष्टि नहीं पाते हैं नहीं कर रहा हूँ - लेकिन unordered_map क्लासिक हैश तालिका डेटा संरचना, आप कर सकते थे set the max_load_factor एक बहुत ही उच्च करने के लिए के अनुसार rehashing है अगर मान लें और जब आप पूरा कर लें तो इसे सामान्य पर रीसेट करें (जो एक रिहाश ट्रिगर करेगा) (या पूर्वानुमानित मूल्य के लिए यदि आप भविष्यवाणी कर सकते हैं कि कितने तत्व हटा दिए जाएंगे)।

क्लासिक हैश तालिका के संदर्भ में, आकार कम होने पर तालिका घटने पर 1/max_load_factor होने पर इसे फिर से शुरू करना चाहिए।

(सुनिश्चित नहीं है कि यह सी ++ में मामला है, लेकिन मुझे लगता है कि यह प्रयास को रोकता है, क्योंकि इसे कार्यान्वित करना वास्तव में आसान है)।

[unord: