एक std :: वेक्टर के itter के सूचकांक प्राप्त करने का सबसे प्रभावी तरीका क्या है?


439

मैं एक वेक्टर पर पुनरावृत्ति कर रहा हूं और सूचकांक की आवश्यकता है जो वर्तमान में इंगित कर रहा है। AFAIK को दो तरीकों से किया जा सकता है:

  • it - vec.begin()
  • std::distance(vec.begin(), it)

इन विधियों के पेशेवरों और विपक्ष क्या हैं?

जवाबों:


558

मैं it - vec.begin()नवीन द्वारा दिए गए विपरीत कारण के लिए सटीक रूप से पसंद करूंगा : यदि आप वेक्टर को एक सूची में बदलते हैं तो यह संकलन नहीं करेगा । यदि आप हर पुनरावृत्ति के दौरान ऐसा करते हैं, तो आप आसानी से O (n) एल्गोरिथ्म को O (n ^ 2) एल्गोरिथम में बदल सकते हैं।

एक अन्य विकल्प, यदि आप पुनरावृत्ति के दौरान कंटेनर में नहीं कूदते हैं, तो इंडेक्स को दूसरे लूप काउंटर के रूप में रखना होगा।

नोट: itएक कंटेनर पुनरावृत्ति के लिए एक सामान्य नाम है std::container_type::iterator it;,।


3
माना। मैं कहूंगा कि माइनस साइन सबसे अच्छा है, लेकिन बेहतर होगा कि std :: दूरी का उपयोग करने की तुलना में एक दूसरा लूप काउंटर रखें, ठीक है क्योंकि यह फ़ंक्शन धीमा हो सकता है।
स्टीवन सुदित

28
बिल्ली क्या है it?
स्टीनफेल्ड

32
@ सेंटिनफेल्ड इट्स एटरेटर। std::container_type::iterator it;
मैट मुन्सन

2
दूसरा लूप काउंटर जोड़ना एक ऐसा स्पष्ट समाधान है कि मैं शर्मिंदा हूं कि मैंने इसके बारे में नहीं सोचा था।
मोर्ड्रेड

3
@ स्वप्निल क्योंकि std::listउनकी स्थिति के अनुसार तत्वों की सीधी पहुँच प्रदान नहीं करता है, इसलिए यदि आप ऐसा नहीं कर सकते हैं list[5], तो आपको करने में सक्षम नहीं होना चाहिए list.begin() + 5
जोस टॉमस टोचिनो

135

मैं पसंद करूंगा std::distance(vec.begin(), it)क्योंकि यह मुझे कंटेनर को बिना किसी कोड परिवर्तन के बदलने की अनुमति देगा। उदाहरण के लिए, आप का उपयोग करने का फैसला करता है, तो std::listबजाय std::vectorजो एक यादृच्छिक अभिगम इटरेटर अपने कोड अभी भी संकलन होगा प्रदान नहीं करता है। चूंकि std :: दूरी इटैलिक लक्षणों के आधार पर इष्टतम विधि चुनती है, तो आपके पास कोई प्रदर्शन गिरावट भी नहीं होगी।


50
जब आप बिना रैंडम एक्सेस के चलने वालों के बिना एक कंटेनर का उपयोग कर रहे हों, तो ऐसी दूरियों की गणना करना सबसे अच्छा नहीं है क्योंकि यह अक्षम है
एली बेंडरस्की

6
@ एली: मैं इससे सहमत हूं, लेकिन एक बहुत ही विशेष मामले में अगर यह वास्तव में आवश्यक है, तो फिर भी वह कोड काम करेगा।
नवीन

9
मुझे लगता है कि कोड को वैसे भी बदलना चाहिए जब कंटेनर बदलता है - एक std :: सूची चर नाम दिया गया vecहै जो बुरी खबर है। यदि कोड को जेनेरिक होने के लिए फिर से लिखा गया था, तो कंटेनर प्रकार को एक टेम्पलेट पैरामीटर के रूप में लेते हुए, कि जब हम कर सकते हैं (और चाहिए) गैर-यादृच्छिक-पहुंच पुनरावृत्तियों को संभालने के बारे में ;-)
स्टीव जेसोप

1
और कुछ कंटेनरों के लिए विशेषज्ञता।
स्कायरअर्डवार्क

19
@SteveJessop: एक वेक्टर का नाम vecहोना बहुत बुरी खबर है, भी।
नदी ताम

74

जैसा कि अंकल बीन्स और नवीन ने दिखाया है, दोनों के लिए अच्छे कारण हैं। कौन सा "बेहतर" है यह इस बात पर निर्भर करता है कि आप क्या व्यवहार चाहते हैं: क्या आप निरंतर समय के व्यवहार की गारंटी देना चाहते हैं, या क्या आप चाहते हैं कि जब आवश्यक हो, तो रैखिक समय पर वापस आ जाए?

it - vec.begin()निरंतर समय लगता है, लेकिन operator -इसे केवल यादृच्छिक अभिगम पुनरावृत्तियों पर परिभाषित किया जाता है, इसलिए कोड उदाहरण के लिए सूची पुनरावृत्तियों के साथ बिल्कुल संकलित नहीं करेगा।

std::distance(vec.begin(), it) सभी पुनरावृत्त प्रकारों के लिए काम करता है, लेकिन केवल रैंडम एक्सेस पुनरावृत्तियों पर उपयोग किए जाने पर एक निरंतर-समय ऑपरेशन होगा।

न तो कोई "बेहतर" है। उस का उपयोग करें जो आपको चाहिए।


1
मैं अतीत में इस से बेईमानी कर चुका हूं। एसटीडी का उपयोग करना: दो एसटीडी पर दूरी :: पुनरावृत्तियों का नक्शा और यह ओ (एन) होने की उम्मीद करना।
स्कायरअर्डवार्क

6
@ScaryAardvark: क्या आपको इसका मतलब हे (1) होने की उम्मीद नहीं है?
jalf

12

मुझे यह पसंद है: it - vec.begin()क्योंकि, यह स्पष्ट रूप से "शुरुआत से दूरी" कहता है। पुनरावृत्तियों के साथ हम अंकगणित के संदर्भ में सोचने के आदी हैं, इसलिए यहाँ -संकेत सबसे स्पष्ट संकेतक है।


19
यह स्पष्ट रूप से उपयोग करने की तुलना में दूरी खोजने के लिए घटाव का उपयोग करने के लिए अधिक स्पष्ट है, काफी शब्द distance?
ट्रैविस गोकेल

4
@Travis, मेरे लिए यह है। यह स्वाद और रिवाज की बात है। हम कहते हैं it++और ऐसा कुछ नहीं है std::increment(it), क्या हम नहीं? यह भी कम स्पष्ट रूप में नहीं गिना जाएगा?
एली बेंडरस्की

3
++ऑपरेटर कैसे हम इटरेटर को बढ़ा देते रूप एसटीएल दृश्यों के भाग के रूप में परिभाषित किया गया है। std::distanceपहले और अंतिम तत्व के बीच तत्वों की संख्या की गणना करता है। तथ्य यह है कि -ऑपरेटर काम करता है केवल एक संयोग है।
ट्रैविस गोकेल

3
@MSalters: और फिर भी, हम
एली बेंडस्की

10

यदि आप पहले से ही std::vector::iteratorऔर std::vector::iteratorकेवल अपने एल्गोरिथ्म को प्रतिबंधित / हार्डकोड कर रहे हैं , तो यह वास्तव में मायने नहीं रखता है कि आप किस विधि का उपयोग करेंगे। आपके एल्गोरिथ्म को पहले से ही उस बिंदु से आगे बढ़ाया जाता है जहां किसी एक को चुनने से कोई फर्क पड़ सकता है। वे दोनों बिल्कुल एक ही काम करते हैं। यह सिर्फ व्यक्तिगत पसंद की बात है। मैं व्यक्तिगत रूप से स्पष्ट घटाव का उपयोग करूंगा।

यदि, दूसरी ओर, आप अपने एल्गोरिथ्म में सामान्यता की एक उच्च डिग्री को बनाए रखना चाहते हैं, अर्थात्, इस संभावना को अनुमति देने के लिए कि भविष्य में किसी दिन यह किसी अन्य पुनरावृत्त प्रकार पर लागू हो सकता है, तो सबसे अच्छा तरीका आपके इरादे पर निर्भर करता है । यह इस बात पर निर्भर करता है कि आप यहाँ इस्तेमाल किए जा सकने वाले itter प्रकार के संबंध में कितना प्रतिबंधात्मक होना चाहते हैं।

  • यदि आप स्पष्ट घटाव का उपयोग करते हैं, तो आपका एल्गोरिथ्म पुनरावृत्तियों के बजाय संकीर्ण वर्ग तक सीमित रहेगा: यादृच्छिक अभिगम पुनरावृत्तियों। (यह वही है जो अब आपको मिलता है std::vector)

  • यदि आप उपयोग करते हैं distance, तो आपका एल्गोरिथ्म पुनरावृत्तियों के बहुत व्यापक वर्ग का समर्थन करेगा: इनपुट पुनरावृत्तियों।

बेशक, distanceगैर-यादृच्छिक-पहुंच पुनरावृत्तियों के लिए गणना सामान्य स्थिति में एक अक्षम ऑपरेशन है (जबकि, फिर से, यादृच्छिक-पहुंच वाले लोगों के लिए यह घटाव के रूप में कुशल है)। यह आपको तय करना है कि आपका एल्गोरिथ्म गैर-यादृच्छिक-पहुंच वाले पुनरावृत्तियों, दक्षता-वार के लिए समझ में आता है या नहीं । यह दक्षता में परिणामी हानि आपके एल्गोरिदम को पूरी तरह से बेकार बनाने के बिंदु पर विनाशकारी है, फिर आपको घटाव के लिए बेहतर रहना चाहिए, इस प्रकार अक्षम उपयोगों को रोकना और उपयोगकर्ता को अन्य पुनरावृत्त प्रकारों के लिए वैकल्पिक समाधान प्राप्त करने के लिए मजबूर करना चाहिए। यदि गैर-यादृच्छिक-पहुंच वाले पुनरावृत्तियों के साथ दक्षता अभी भी प्रयोग करने योग्य सीमा में है, तो आपको distanceइस तथ्य का उपयोग और दस्तावेज करना चाहिए कि एल्गोरिथ्म यादृच्छिक-पहुंच पुनरावृत्तियों के साथ बेहतर काम करता है।


4

Http://www.cplusplus.com/reference/std/iterator/distance/ के अनुसार , चूंकि vec.begin()एक यादृच्छिक अभिगमकर्ता है, दूरी विधि -ऑपरेटर का उपयोग करता है ।

तो जवाब है, प्रदर्शन के दृष्टिकोण से, यह समान है, लेकिन शायद distance()यह समझना आसान है कि क्या किसी को आपके कोड को पढ़ना और समझना होगा।


3

मैं केवल -संस्करण का उपयोग करूँगा std::vector- यह बहुत स्पष्ट है कि इसका क्या मतलब है, और ऑपरेशन की सादगी (जो एक सूचक घटाव से अधिक नहीं है) को सिंटैक्स द्वारा व्यक्त किया जाता है ( distanceदूसरी तरफ, पाइथागोरस की तरह लगता है) पहले पढ़ना, है ना?)। जैसा कि अंकल बताते हैं, -यह भी एक स्टेटिक अभिकथन के रूप में कार्य करता है कि मामले vectorमें गलती से बदल दिया गया है list

इसके अलावा, मुझे लगता है कि यह बहुत अधिक सामान्य है - हालांकि, इसे साबित करने के लिए कोई संख्या नहीं है। मास्टर तर्क: it - vec.begin()स्रोत कोड में कम है - कम टाइपिंग का काम, कम जगह की खपत। जैसा कि यह स्पष्ट है कि आपके प्रश्न का सही उत्तर स्वाद का मामला है, यह एक मान्य तर्क भी हो सकता है।


0

सूचकांक के साथ 10 के "सभी" घटनाओं को खोजने के लिए यहां एक उदाहरण है। सोचा कि इससे कुछ मदद मिलेगी।

void _find_all_test()
{
    vector<int> ints;
    int val;
    while(cin >> val) ints.push_back(val);

    vector<int>::iterator it;
    it = ints.begin();
    int count = ints.size();
    do
    {
        it = find(it,ints.end(), 10);//assuming 10 as search element
        cout << *it << " found at index " << count -(ints.end() - it) << endl;
    }while(++it != ints.end()); 
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.