2014-05-21 11 views
6

के पीछे एक वेक्टर तत्व को स्थानांतरित करना क्या तत्व को मिटाने और इसे वापस जोड़ने के अलावा कोई बेहतर तरीका है (या तो तेज़ या कोड के कम प्रतीकों के साथ)?वेक्टर

template <typename T> 
void moveItemToBack(std::vector<T>& v, size_t itemIndex) 
{ 
    T tmp(v[itemIndex]); 
    v.erase(v.begin() + itemIndex); 
    v.push_back(tmp); 
} 
+0

वास्तव में नहीं है ... वेक्टर उन चीज़ों को स्टोर करने का एक बहुत ही प्रभावी तरीका नहीं है जिन्हें शुरुआत से हटाया जाना आवश्यक है। 'Std :: queue' या' std :: dequeue' – IdeaHat

+0

@MadScienceDreams पर देखें: std :: dequeue यहां बेहतर नहीं है, और मुझे यादृच्छिक पहुंच की आवश्यकता है। –

+0

फिर उपयोग करने के लिए कुशल संरचना अपने स्वयं के अंगूठी बफर बनाने के लिए है। – IdeaHat

उत्तर

27

आप मानक पुस्तकालय से std::rotate के साथ ऐसा कर सकते हैं। चूंकि यह वेक्टर आकार को नहीं बदलता है, यह भी एक पुनर्वितरण ट्रिगर नहीं करेगा। आपका समारोह कुछ इस तरह दिखेगा:

template <typename T> 
void moveItemToBack(std::vector<T>& v, size_t itemIndex) 
{ 
    auto it = v.begin() + itemIndex; 
    std::rotate(it, it + 1, v.end()); 
} 
+1

यही स्टेपानोव (एसटीएल डिज़ाइन किया गया है) अनुशंसा करता है: http://www.stepanovpapers.com/notes.pdf, पृष्ठ। 154. –

+0

बस एक नोट: अगर मैं इसे सही ढंग से पढ़ रहा हूं, तो इसमें ओ (एन) जटिलता है। नीचे 'std :: swap' समाधान जटिलता ओ (1) है। – imallett

+1

@imallett आप सही हैं। यह उत्तर स्थानांतरित आइटम के अलावा अन्य तत्वों के क्रम को संरक्षित करता है जबकि अन्य उत्तर नहीं होता है। जैसा कि कहा गया है, सवाल स्पष्ट नहीं था कि क्या यह एक आवश्यकता थी। संरक्षण आदेश अधिक महंगा है। – Blastfurnace

3

आप अतिरिक्त चर से बच सकते हैं।

v.push_back(v[itemIndex]); 
v.erase(v.begin() + itemIndex); 

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

+0

आह, ज़ाहिर है, साफ! धन्यवाद। बीटीडब्लू, क्या यहां 'push_back' की बजाय 'emplace_back' का उपयोग करने का कोई लाभ है? –

+0

@ व्हायोलेट जिराफ, यदि 'टी' छोटा है, तो' emplace_back' 'push_back' से तेज होने की संभावना नहीं है। यदि 'टी' बड़ा है तो मुझे वास्तव में यकीन नहीं है। – Brian

+1

@ ब्रायन emplace_back वास्तव में कक्षा के लिए निर्माता को कॉल करता है, जो इस कॉल के साथ कॉपी कन्स्ट्रक्टर को कम कर देगा ... इसलिए इस मामले में, मुझे नहीं लगता कि इससे कोई फर्क नहीं पड़ता। आप C++ 11 में चालक कन्स्ट्रक्टर का उपयोग करके ट्रिगर करने के लिए 'v.push_back (std :: move (v [itemIndex)) 'कर सकते हैं। – IdeaHat

5

संभवत: सबसे तेज़ तरीका है, पिछले तत्व

template <typename T> 
void moveItemToBack(std::vector<T>& v, size_t itemIndex) 
{ 
    std::swap(v[itemIndex], v.back()); // or swap with *(v.end()-1) 
} 

एक ऑपरेशन के साथ यह स्वैप करने के लिए होगा! संभोग std::swapT

+3

यह एक स्पष्ट समाधान है, लेकिन यह वस्तुओं को क्रमशः एक अंत तक आगे बढ़ने से परे बदल देता है। –

+0

@VioletGiraffe घुमावदार नहीं है? –

+0

@ व्हायोलेट जिराफ ओके अब आपको जो मिला है वह मिला है। जब तक रिश्तेदार आदेश नहीं बदलता तब तक घूमना ठीक है।मैं सिर्फ प्रश्न के लिए एक शाब्दिक उत्तर दे रहा था "एक तत्व को पीछे की ओर ले जाएं" –