2012-02-25 33 views
13

पर pop_front को लागू करने का तेज़ तरीका मैं std :: vector का उपयोग करने वाले कुछ वर्गों और कई उपयोगिता विधियों का उपयोग कर रहा हूं।एक std :: vector

अब मुझे प्रत्येक वर्ग को उन वर्गों में से एक पर pop_front - push_back विधि का उपयोग करने की आवश्यकता है (लेकिन वे सभी जुड़े हुए हैं, और एक साथ काम करते हैं इसलिए मैं केवल एक ही नहीं बदल सकता)।

अधिकांश ऑपरेशन सभी तत्वों और पुश_बैक ऑपरेशंस पर पुनरावृत्त होते हैं, इसलिए मुझे सबसे अच्छे काम के लिए क्या करना चाहिए: उन वर्गों और उपयोगिताओं के भंडार को फोर्क करें, सबकुछ टेम्पलेट करें और डेक या सूची का उपयोग करें।

लेकिन इसका मतलब है कि बहुत सारे कोड पुनर्लेखन और बहुत सारे परीक्षण से मुझे समय सीमा याद आती है।

इसलिए मुझे एक स्थिर-आकार वाले वेक्टर (आकार में परिवर्तन नहीं होगा) के लिए एक कुशल पॉप_फ्रंट लिखने की सलाह चाहिए।

मैं here एक रास्ता मिल गया है:

template<typename T> 
void pop_front(std::vector<T>& vec) 
{ 
    vec.front() = vec.back(); 
    vec.pop_back(); 
    vec.front() = vec.back(); // but should this work? 
} 

और एक और विचार किया जाना चाहिए:

template<typename T> 
void pop_front(std::vector<T>& vec, already_allocated_vector vec1) 
{ 
    vec1.clear(); 
    copy(vec.begin(), vec.end()-1, vec1.begin()); 
    copy(vec1.begin(), vec1.end(), vec.begin()); 
} 

इन दोनों के समाधान के लिए तेजी से क्या है? कोई अन्य समाधान?

+0

"आकार बदल नहीं जाएगा" का क्या मतलब है? Pop_front करने के बाद, वेक्टर पहले जैसा ही आकार होगा? यदि हां, तो अंतिम तत्व कचरा होना चाहिए? –

+0

वेक्टर का आकार समान है, क्योंकि एक पॉप के बाद मैं अचानक धक्का देता हूं। प्रत्येक फ्रेम मैंने एक ही विधि में एक पॉप और पुश बनाया ताकि इस विधि से पहले और बाद में वेक्टर उसी आकार का हो – nkint

+4

गति के बारे में चिंता करने से पहले, ** शुद्धता ** के बारे में चिंता करें। दुनिया में सभी गति का मतलब कुछ भी नहीं है यदि आपको मिलने वाला नतीजा सिर्फ सादा गलत है, और जहां तक ​​मैं कह सकता हूं, तो आपके उम्मीदवार गलत हैं। पहले व्यक्ति को 'pop_back_and_overwrite_front_with_penultimate' नाम दिया जाना चाहिए, और दूसरे को' invoke_undefined_behavior_and_pop_back' नाम दिया जाना चाहिए। ('Vec1.begin()' को लिखना अनिर्धारित है क्योंकि 'vec1' खाली है; आपको 'vec1.clear()' के बजाय' vec1.resize (vec.size() - 1) लिखना होगा।) जब मैं वेक्टर ऑपरेशंस से निपट रहा हूं, तो मैं कभी-कभी एक तस्वीर खींचता हूं। शायद वह भी आपकी मदद करेगा। –

उत्तर

21

मैं उम्मीद करेंगे:

template<typename T> 
void pop_front(std::vector<T>& vec) 
{ 
    assert(!vec.empty()); 
    vec.front() = std::move(vec.back()); 
    vec.pop_back(); 
} 

ऐसा करने का सबसे कारगर तरीका हो सकता है, लेकिन यह वेक्टर में तत्वों की व्यवस्था बनाए रखने नहीं है।

आप vec में शेष तत्वों का क्रम बनाए रखने की जरूरत है, तो आप कर सकते हैं:

template<typename T> 
void pop_front(std::vector<T>& vec) 
{ 
    assert(!vec.empty()); 
    vec.erase(vec.begin()); 
} 

यह vec में तत्वों की संख्या में रेखीय समय होगा, लेकिन यह सबसे अच्छा तुम कर सकते है अपनी डेटा संरचना को बदलने के बिना।

इन कार्यों एक निरंतर आकार में vector बनाए रखेंगे में से कोई, क्योंकि एक pop_front आपरेशन परिभाषा से एक कंटेनर से एक तत्व निकाल देंगे।

+0

मुझे ऑर्डर चाहिए .. – nkint

+0

मुझे लगता है कि यह माना जाता है कि ऑर्डर को संरक्षित किया जाना चाहिए क्योंकि 'std :: vector :: pop_back' ऑर्डर संरक्षित करता है । – HelloGoodbye

+0

'vec.push_back (new_value) vec.shrink_to_fit()' बाद में बेहतर नहीं है? –

5

pop_front() के बाद से केवल पहला तत्व मिटा देता है, प्रत्यक्ष कार्यान्वयन यह है:

template <typename V> 
void pop_front(V & v) 
{ 
    assert(!v.empty()); 
    v.erase(v.begin()); 
} 

अब के लिए गति के बारे में चिंता मत करो। यदि आप वापस जाना और कोड अनुकूलित करना चाहते हैं, तो समर्पित परियोजना समय के लिए पूछें।

+2

यह एक 'pop_everything_but_front' फ़ंक्शन की तरह दिखता है ... – Mankarse

+0

क्षमा करें, मैं आपके कोड को समझ नहीं पा रहा हूं, यह केवल पहले तत्व को नहीं देखता है? मैं केवल पहले तत्व को मिटाना चाहता हूं, यह नहीं होना चाहिए: v.erase (v.begin(), v.begin() + 1); ? – nkint

+0

@Mankarse: हाँ, डी ओह! धन्यवाद! –

3

आप IgushArray (https://github.com/igushev/IgushArray) भी कर सकते हैं जो किसी सरणी की तरह स्थिर निरंतर-समय पहुंच ऑपरेशन होता है, लेकिन सम्मिलित/मिटा ऑपरेशन केवल ओ (एन^1/2) समय लेता है। तो, शुरुआत में डालने के मामले में यहां बहुत प्रभावी होगा। सावधान रहें, संरचना आरक्षित() के लिए बहुत संवेदनशील है।

template <class T> 
void pop_front(IgushArray<T>& v) 
{ 
    if (!v.empty()) 
    v.erase(v.begin()); 
} 

पहले विकल्प में आपने लिखा है कि आप तत्वों के आदेश का उल्लंघन करते हैं। क्या यह एक मुद्दा है?

यदि ऐसा है, तो मैंने लिखा संस्करण का उपयोग करें।

यदि तत्वों का आदेश और क्रम बिल्कुल कोई फर्क नहीं पड़ता है, तो यह std :: set या std :: multiset का उपयोग करना बेहतर हो सकता है।

1

तुम सिर्फ समारोह प्रयोग में तो पहला तत्व मिटाने का प्रयास करता है, तो:

if (my_vector.size()){ //check if there any elements in the vector array 
    my_vector.erase(my_vector.begin()); //erase the firs element 
} 

अगर आप पूरी सदिश सरणी के लिए पॉप सामने अनुकरण करने के लिए चाहते हैं (आप पॉप करने के लिए शुरू से ही हर तत्व बाहर रखना चाहते हैं अंत), मैं सुझाव देता हूं:

reverse(my_vector.begin(),my_vector.end()); // reverse the order of the vector array 
my_vector.pop_back(); // now just simple pop_back will give you the results 
संबंधित मुद्दे