2008-11-11 25 views
5

मेरे पास दो एसटीएल कंटेनर हैं जिन्हें मैं एक से अधिक बार दिखाई देने वाले किसी भी तत्व को हटाने, विलय करना चाहता हूं। उदाहरण के लिए:डुप्लिकेट तत्वों को हटाने, एकाधिक एसटीएल कंटेनरों को मर्ज करने का सबसे अच्छा तरीका?

typedef std::list<int> container; 
container c1; 
container c2; 

c1.push_back(1); 
c1.push_back(2); 
c1.push_back(3); 

c2.push_back(2); 
c2.push_back(3); 
c2.push_back(4); 

container c3 = unique_merge(c1, c2); 
// c3 now contains the following 4 elements: 
// 1, 2, 3, 4 

std :: अद्वितीय केवल आसन्न तत्वों के लिए हो रहा है और मेरे मामले में कंटेनर किसी भी क्रम में हो सकता है।

container unique_merge(const container& c1, const container& c2) 
{ 
    std::set<container::value_type> s; 
    BOOST_FOREACH(const container::value_type& val, c1) 
     s.insert(val); 
    BOOST_FOREACH(const container::value_type& val, c2) 
     s.insert(val); 
    return container(s.begin(), s.end()); 
} 

वहाँ एक बेहतर तरीका है या मैं खून बह रहा है स्पष्ट कुछ छूट गया है: मैं कुछ std :: प्रवंचना सेट मुझे लगता है कि कर सकता है?

+0

यदि आप कुछ "रक्तस्राव स्पष्ट" मांगते हैं, तो आपका कार्यान्वयन मौसमी मामलों के लिए पर्याप्त है। लेकिन ओ (एन * लॉग (एम)) की लागत पर एक बेहतर एल्गोरिदम मौजूद है, जहां एन सभी कंटेनरों में तत्वों की कुल संख्या है, और एम कंटेनरों की संख्या है। कोड छोटा नहीं है, जब मेरे पास समय है तो मैं बाद में लिखूंगा। – RnMss

उत्तर

4

एक अनियमित सूचियों के लिए, आपकी सेट चाल शायद सबसे अच्छी है। यह प्रत्येक सम्मिलन ओ (लॉग एन) होना चाहिए, जिसमें एन आवेषण आवश्यक हैं, और ट्रैवर्सिंग ओ (एन) होगी, जो आपको ओ (एन * लॉग एन) देगी। दूसरा विकल्प अलग-अलग सूची में std :: sort को चलाने के लिए है और फिर std::set_union का उपयोग करके समानांतर में उनके माध्यम से चलना है, जो आपके लिए डुप्लीकेट हटा देता है। यह ओ (एन * लॉग एन) भी होगा, इसलिए यदि आप प्रदर्शन के बारे में चिंतित हैं, तो आपको प्रोफ़ाइल करना होगा। यदि आप नहीं हैं, तो जो भी आपको अधिक समझ में आता है।

संपादित करें: set_union तभी मूल सूचियों में कोई डुप्लिकेट हैं काम करेंगे, अन्यथा आप sort, merge, unique और erase साथ जाने के लिए होगा। बड़ा ओ प्रदर्शन अभी भी वही है, प्रोफाइलिंग के बारे में एक ही चेतावनी के साथ।

template <typename container> 
container unique_merge(container c1, container c2) 
{ 
    std::sort(c1.begin(), c1.end()); 
    std::sort(c2.begin(), c2.end()); 
    container mergeTarget; 
    std::merge(c1.begin(), c1.end(), c2.begin(), c2.end(), 
     std::insert_iterator(mergeTarget, mergeTarget.end()) 
    ); 
    std::erase(
     std::unique(mergeTarget.begin(), mergeTarget.end()), 
     mergeTarget.end() 
    ); 

    return mergeTarget; 
} 
+0

std :: set_union के विनिर्देश के अनुसार: यदि दो श्रेणियों, आर 1 और आर 2 में डुप्लिकेट तत्व हैं, तो वी कहते हैं कि आर 1 में एम बार और आर 2 में एम बार होता है, std :: set_union के परिणाम में अधिकतम (एन , एम) वी के उदाहरण। तो जब तक एन <= 1 और एम <= 1 यह सही समाधान नहीं है। –

+1

आपका कोड 2 कॉन्स कंटेनर टाइप करता है। वह संकलन भी नहीं करेगा। –

+0

यही वह है जो मुझे परीक्षण-संकलन के लिए नहीं मिलता है। – Eclipse

-1

क्या आप उन्हें मर्ज करने के लिए std::merge का उपयोग नहीं कर सकते हैं और फिर डुप्लीकेट हटा सकते हैं? हालांकि, कंटेनरों को सॉर्ट करने की आवश्यकता होती है, हालांकि।

+0

std :: set_union एल्गोरिदम पहले से ही करता है। – Uhall

3

एसटीएल से std::set_union algorithm का उपयोग करें। आपको पहले अपनी इनपुट सूचियों को क्रमबद्ध करने की आवश्यकता होगी - या अपनी इनपुट सूचियों की प्रतियां बनाएं, उन्हें सॉर्ट करें, फिर std :: set_union का उपयोग करें।

2

आपको या तो क्रमबद्ध करने की आवश्यकता होगी (या तो स्पष्ट रूप से, या निश्चित रूप से सेट किए गए सॉर्ट किए गए कंटेनर के माध्यम से)।

एक कंटेनर में अद्वितीय तत्व प्राप्त करने के लिए std :: sort/std :: अद्वितीय/std :: मिटा का उपयोग कर एक सामान्य मुहावरे है।

तो सी 1 की सामग्री के साथ एक कंटेनर बनाएं, सी 2 की सामग्री संलग्न करें, फिर क्रमबद्ध करें, अद्वितीय तत्वों को अंत में ले जाएं, और उन्हें मिटा दें। कुछ ऐसा:

container c(c1.begin(), c1.end()); 
c.insert(c.end(), c2.begin(), c2.end()); 
c.erase(std::unique(c.begin(), c.end()), c.end()); 
संबंधित मुद्दे

 संबंधित मुद्दे