क्या std के माध्यम से पुनरावृत्ति का क्रम :: ज्ञात मानचित्र (और मानक द्वारा गारंटी) है?


158

मेरे कहने का मतलब है - हम जानते हैं कि std::mapकुंजी के अनुसार तत्वों को क्रमबद्ध किया जाता है। तो, मान लें कि कुंजियाँ पूर्णांक हैं। अगर मैं एक std::map::begin()का std::map::end()उपयोग करने से पुनरावृत्ति forकरता हूं, तो क्या मानक गारंटी देता है कि मैं कुंजी के साथ तत्वों के माध्यम से पुनरावृति करूंगा, आरोही क्रम में क्रमबद्ध?


उदाहरण:

std::map<int, int> map_;
map_[1] = 2;
map_[2] = 3;
map_[3] = 4;
for( std::map<int, int>::iterator iter = map_.begin();
     iter != map_.end();
     ++iter )
{
    std::cout << iter->second;
}

क्या यह प्रिंट करने की गारंटी है 234या क्या यह कार्यान्वयन को परिभाषित करता है?


वास्तविक जीवन कारण: मैं एक है std::mapके साथ intकुंजी। बहुत ही दुर्लभ स्थितियों में, मैं सभी तत्वों के माध्यम से पुनरावृति करना चाहता हूं, कुंजी के साथ, एक ठोस intमूल्य से अधिक । हां, ऐसा लगता है कि यह std::vectorबेहतर विकल्प होगा, लेकिन मेरी "बहुत दुर्लभ स्थितियों" पर ध्यान दें।


संपादित करें : मुझे पता है, कि तत्वों std::mapको हल किया गया है .. इसे इंगित करने की आवश्यकता नहीं है (यहां अधिकांश उत्तरों के लिए)। मैंने इसे अपने प्रश्न में भी लिखा था।
मैं पुनरावृत्तियों और आदेश के बारे में पूछ रहा था जब मैं एक कंटेनर के माध्यम से पुनरावृत्ति कर रहा हूं। धन्यवाद @Kerrek उत्तर के लिए एस.बी.


6
मामले में आप नहीं जानते थे: अपने वास्तविक जीवन के उपयोग में आप इसका इस्तेमाल कर सकते हैं map::upper_boundकि आप इसे शुरू करने के लिए बिंदु खोजें।
स्टीव जेसप

मुझे यह पता है और मुझे पता है कि मैं जिस स्थान पर चलना शुरू कर रहा हूं, वह सही है। मैं सिर्फ भटक गया अगर आदेश की गारंटी है।
किरिल किरोव

यदि आपकी कुंजियाँ (सांख्यिक सूचकांकों) पूरे बोर्ड में बहुत भिन्न होती हैं, तो एक विरल वेक्टर समझदार नहीं होगा। मैं एक समान समाधान का उपयोग कर रहा हूं, जिसके लिए संख्यात्मक सूचकांक कार्टेशियन y- 3-आयामी स्थान में समन्वय करता है। इस परिदृश्य में एक वेक्टर का उपयोग करने से गीगाबाइट्स द्वारा मेरी मेमोरी के पदचिह्न में वृद्धि होगी। इसलिए मुझे नहीं लगता कि वेक्टर यहाँ एक रामबाण दवा है, इससे बहुत दूर है।
जोनाथन न्यूफेल्ड

मुझे सवाल समझ में नहीं आता है, और मैं समझाता हूँ कि एक विचार-प्रयोग के माध्यम से क्यों। यदि आप पहले से ही जानते हैं कि तत्वों का आदेश दिया गया है, तो पुनरावृत्ति कैसे नहीं हो सकती है? आदेश का क्या मतलब है, अगर यह पुनरावृत्ति पर लागू नहीं होता है? अन्य मामले क्या हैं जहां आदेश मायने रखता है, पता लगाने योग्य है, आदि। (जवाब कॉन्स्टेंटिन द्वारा दिया गया था ।)
अंडरस्कोर_ड

जवाबों:


176

हाँ, यह गारंटी है। इसके अलावा, *begin()आपको सबसे छोटा और *rbegin()सबसे बड़ा तत्व देता है, जैसा कि तुलना ऑपरेटर द्वारा निर्धारित किया गया है, और दो प्रमुख मूल्य aऔर bजिसके लिए अभिव्यक्ति !compare(a,b) && !compare(b,a)सही है, को समान माना जाता है। डिफ़ॉल्ट तुलना फ़ंक्शन है std::less<K>

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


एसटीडी :: नक्शा बाइनरी पेड़ों का उपयोग करके लागू किया जाता है, इसलिए तकनीकी रूप से कोई बाइनरी खोज नहीं की जाती है।
jupp0r

11
@ jupp0r: बाइनरी सर्च ट्री के रूप में एक रेंज को संरचित करना रेंज के माध्यम से बाइनरी सर्च को लागू करने के लिए एक विशेष विधि है। "बाइनरी सर्च" एक विशेष कार्यान्वयन के बजाय एक अमूर्त अवधारणा है। इससे कोई फर्क नहीं पड़ता कि आप किसी सरणी में ऑफ़सेट से कूदते हैं या लिंक नोड का अनुसरण करते हैं; वे "सीमा को द्विभाजित करने" के विशिष्ट तरीके हैं।
केरेक एसबी

1
मुझे पता है कि यह एक पुरानी पोस्ट है, लेकिन स्पष्ट होना "कुशल खोज" सापेक्ष है। तकनीकी रूप std::unordered_mapसे O (1) का अधिक कुशल लुकअप समय है। लाभ std::mapप्रमुख आदेश देने में है, लेकिन देखने में नहीं।
एडम जॉनसन

42

यह C ++ मानक में एसोसिएटिव कंटेनर आवश्यकताओं द्वारा गारंटीकृत है। जैसे C ++ 11 में 23.2.4 / 10 देखें:

सहयोगी कंटेनरों के चलने वालों की मौलिक संपत्ति यह है कि वे
कंटेनरों के माध्यम से पुनरावृति कुंजियों के गैर-अवरोही क्रम में जहां
गैर-अवरोही की तुलना उनके निर्माण के लिए उपयोग की गई तुलना द्वारा परिभाषित की गई है।
किन्हीं भी दो से चलने योग्य पुनरावृत्तियों के लिए i और j ऐसी है कि i से j की दूरी है
सकारात्मक,
  value_comp (* j, * i) == झूठी

और 23.2.4 / 11

अद्वितीय कुंजी के साथ सहयोगी कंटेनरों के लिए मजबूत स्थिति रखती है,
  value_comp (* i, * j)! = false है।

32

मुझे लगता है कि डेटा संरचनाओं में एक भ्रम है।

अधिकांश भाषाओं में, एक mapबस एक सहयोगी है: यह एक मूल्य के लिए एक कुंजी मैप करता है। "नई" भाषाओं में, यह आमतौर पर हैश मैप का उपयोग करके प्राप्त किया जाता है, इस प्रकार किसी भी आदेश की गारंटी नहीं होती है।

C ++ में, हालांकि, ऐसा नहीं है:

  • std::mapएक सॉर्टेड एसोसिएटिव कंटेनर है
  • std::unordered_map एक हैश-टेबल आधारित सहयोगी कंटेनर है जो C ++ 11 में पेश किया गया है

इसलिए, आदेश देने की गारंटी को स्पष्ट करने के लिए।

C ++ 03 में:

  • std::set, std::multiset, std::mapऔर std::multimapकुंजी के अनुसार आदेश दिया जा करने के लिए गारंटी दी जाती है (और कसौटी आपूर्ति)
  • में std::multisetऔर std::multimap, मानक बराबर तत्वों पर किसी भी क्रम गारंटी लागू नहीं करता (यानी, उन जो बराबर की तुलना में)

C ++ 11 में:

  • std::set, std::multiset, std::mapऔर std::multimapकुंजी के अनुसार आदेश दिया जा करने के लिए गारंटी दी जाती है (और कसौटी आपूर्ति)
  • में std::multisetऔर std::multimap, स्टैंडर्ड लगाता है कि बराबर तत्वों (उन जो बराबर की तुलना में) उनकी प्रविष्टि आदेश के अनुसार आदेश दिया जाता है (पहले पहले डाला)
  • std::unordered_*कंटेनर हैं, जैसा कि नाम का अर्थ है, आदेश नहीं दिया गया है। सबसे विशेष रूप से, कंटेनर के संशोधित होने पर (सम्मिलन / हटाने पर) तत्वों का क्रम बदल सकता है।

जब मानक कहता है कि तत्वों को एक तरह से आदेश दिया गया है, तो इसका मतलब है कि:

  • पुनरावृति करते समय, आप तत्वों को परिभाषित क्रम में देखते हैं
  • जब रिवर्स में पुनरावृत्ति होती है, तो आप तत्वों को विपरीत क्रम में देखते हैं

मुझे उम्मीद है कि यह किसी भी भ्रम को साफ करता है।


इसका मेरे सवाल से कोई लेना-देना नहीं है, क्षमा करें :) मुझे पता है कि किसको आदेश दिया गया है, और कौन सा नहीं। और जब मैं तत्वों के माध्यम से पुनरावृत्ति कर रहा हूं, तो मैं उस आदेश के लिए पूछ रहा हूं।
किरिल किरोव

10
@KirilKirov: ठीक है, एक आदेश दिए गए साहचर्य कंटेनर की परिभाषा यह है कि जब इसके माध्यम से पुनरावृत्ति होती है तो तत्वों का आदेश दिया जाता है।
मथिउ एम।

ठीक है, मुझे लगता है कि आप सही हैं, लेकिन मुझे नहीं पता था और यह वही है जो मैं पूछ रहा था :)
किरिल किरोव

4

क्या यह 234 प्रिंट करने की गारंटी है या इसे लागू करने की परिभाषा है?

हाँ, std::mapएक सॉर्ट किया गया कंटेनर है, Keyजो आपूर्ति के साथ आदेश दिया गया है Comparator। तो इसकी गारंटी है।

मैं सभी तत्वों के माध्यम से चलना चाहता हूँ, कुंजी के साथ, एक ठोस int मान से अधिक।

यह निश्चित रूप से संभव है।


3

हाँ ... तत्वों में एक std::mapसख्त कमजोर-क्रम है, जिसका अर्थ है कि तत्व एक सेट से बने होंगे (यानी, "बराबर" होने वाली चाबियों का कोई दोहराव नहीं होगा), और समानता किसी भी परीक्षण से निर्धारित होती है दो कुंजी A और B, यदि कुंजी A, B से कम नहीं है, और B A से कम नहीं है, तो कुंजी A, B से समान है।

कहा जा रहा है, अगर आप उस प्रकार के तत्वों को ठीक से क्रमबद्ध नहीं कर सकते हैं, तो std::mapउस प्रकार के लिए कमजोर-क्रम अस्पष्ट है (आपके मामले में, जहाँ आप पूर्णांक को कुंजी-प्रकार के रूप में उपयोग कर रहे हैं, यह समस्या नहीं है)। आपको एक ऑपरेशन को परिभाषित करने में सक्षम होना चाहिए जो आपके द्वारा कुंजियों के लिए उपयोग किए जा रहे प्रकार पर कुल आदेश को परिभाषित करता है std::map, अन्यथा आपके पास केवल आपके तत्वों के लिए एक आंशिक आदेश होगा, या पॉसेट, जिसमें ऐसी संपत्ति है जहां ए की तुलना नहीं की जा सकती है। बी इस परिदृश्य में आमतौर पर क्या होगा कि आप कुंजी / मूल्य जोड़े सम्मिलित करने में सक्षम होंगे, लेकिन यदि आप पूरे मानचित्र के माध्यम से पुनरावृति करते हैं, और "लापता" का पता लगाते हैं, तो आप डुप्लिकेट कुंजी / मूल्य जोड़े के साथ समाप्त हो सकते हैं। कुंजी / मूल्य जोड़े जब आप std::map::find()मानचित्र में एक विशिष्ट कुंजी / मूल्य जोड़ी का प्रदर्शन करने का प्रयास करते हैं ।


अन्य उत्तरों के रूप में, यह वास्तव में मेरे प्रश्न का उत्तर नहीं देता है, वैसे भी धन्यवाद।
किरिल किरोव

-3

शुरू () सबसे छोटा तत्व दे सकता है। लेकिन इसे लागू किया गया है। क्या यह सी ++ मानक में निर्दिष्ट है? यदि नहीं, तो यह धारणा बनाना खतरनाक है।

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