2012-04-01 16 views
6

मैं एक से अधिक डेटा प्रविष्टियों को निम्न जानकारी शामिल है: ID_NUMBER name1 तारीख NAME2सी ++ कई तत्वों के साथ डबल छंटाई डेटा

यह इस तरह एक struct में डाल करना संभव है:

struct entry { 
    int id_number; 
    string name1; 
    int date; 
    string name2; 
} 

मेरे डेटा में, मेरे पास ऐसी कई प्रविष्टियां हैं और मैं सॉर्ट करना चाहता हूं। सबसे पहले, मैं नाम 1 के आधार पर वर्णानुक्रम में क्रमबद्ध करना चाहता हूं, फिर तिथि के आधार पर क्रमबद्ध करें। हालांकि, तिथि के आधार पर क्रमबद्ध वर्णमाला का सबसेट है, उदा। अगर मेरे पास एक ही नाम 1 के साथ दो प्रविष्टियां हैं, तो मैं तिथि के अनुसार उन प्रविष्टियों को ऑर्डर करना चाहता हूं। इसके अलावा, जब मैं सॉर्ट करता हूं, मैं चाहता हूं कि प्रविष्टि के तत्व एक साथ रहें, इसलिए सभी चार मान एक साथ चलते हैं।

मेरे सवालों का इस प्रकार हैं:

1) डेटा संरचना किस प्रकार मैं इस डेटा रखने के लिए इस्तेमाल करना चाहिए तो मैं उनमें से किसी एक के द्वारा जब मैं प्रकार किसी भी एक साथ चार तत्वों के सेट रख सकते हैं?

2) इस सॉर्टिंग को करने का सबसे तेज़ तरीका क्या है (कोड लिखने के लिए समय की मात्रा के मामले में)। आदर्श रूप से, मैं एल्गोरिदम.h में इस प्रकार की तरह कुछ उपयोग करना चाहता हूं क्योंकि यह पहले से ही बनाया गया है।

3) क्या एसटीएल में डेटा संरचना में कुछ बनाया गया है जो मैंने कुशलता से वर्णित डबल सॉर्टिंग को संभाल सकता है?

उत्तर

5

struct आपके पास, ठीक है सिवाय इसके कि आप operator< की एक अधिभार जोड़ने के लिए तुलना कर सकते हैं। यहाँ मैं कर रहा हूँ ", तो तारीख नाम से तुलना करें" तुलना:

// Add this as a member function to `entry`. 
bool operator<(entry const &other) const { 
    if (name1 < other.name1) 
     return true; 
    if (name1 > other.name1) 
     return false; 

    // otherwise name1 == other.name1 
    // so we now fall through to use the next comparator. 

    if (date < other.date) 
     return true; 
    return false; 
} 

[संपादित करें: क्या आवश्यक है एक "सख्त कमजोर आदेश" कहा जाता है। यदि आप साधनों के बारे में विस्तार से जानना चाहते हैं, और कौन से विकल्प संभव हैं, डेव अब्राहम ने इसके बारे में C++ Next पर विस्तृत पोस्ट लिखा है।

उपरोक्त मामले में, हम दोनों के नाम 1 फ़ील्ड की तुलना करके शुरू करते हैं। यदि a<b, तो हम तुरंत सत्य लौटते हैं। अन्यथा, हम a>b की जांच करते हैं, और यदि ऐसा है तो हम झूठी वापसी करते हैं। उस बिंदु पर, हमने a<b और a>b को समाप्त कर दिया है, इसलिए हमने यह निर्धारित किया है कि a==b, जिस स्थिति में हम तिथियों का परीक्षण करते हैं - यदि a<b, हम सत्य वापस आते हैं। अन्यथा, हम झूठी वापसी करते हैं - या तो तिथियां बराबर होती हैं, या b>a, जिनमें से कोई भी a<b के लिए परीक्षण गलत है। अगर सॉर्ट को सॉर्ट करने की आवश्यकता है (कोई इरादा नहीं है) तो इनमें से कौन सा मामला है, यह फिर से फ़ंक्शन को स्वैप किए गए तर्कों के साथ कॉल कर सकता है। नाम अभी भी बराबर होंगे, इसलिए यह अभी भी तारीखों पर आ जाएगा - अगर हम झूठे होते हैं, तो तिथियां बराबर होती हैं। अगर हम स्वैप की तारीखों पर सच हो जाते हैं, तो दूसरी तारीख के रूप में शुरू हुआ वास्तव में अधिक है। ]

operator< संरचना में परिभाषित आप उस क्रम को परिभाषित करते हैं जो डिफ़ॉल्ट रूप से उपयोग किया जाएगा।जब/अगर आप आप के लिए एक और आदेश निर्दिष्ट कर सकते हैं चाहते हैं उपयोग करने के लिए छँटाई:

struct byid { 
    bool operator<(entry const &a, entry const &b) { 
     return a.id_number < b.id_number; 
    } 
}; 

std::vector<entry> entries; 

// sort by name, then date 
std::sort(entries.begin(), entries.end()); 

// sort by ID 
std::sort(entries.begin(), entries.end(), byid()); 
+0

उसे एक स्थिर प्रकार की आवश्यकता है या यह काम नहीं करेगा। मैं अपना खुद का उत्तर देने से पहले ही कहूंगा क्योंकि यह आपके जैसा बहुत कुछ होगा, इस बारे में टिप्पणी के अलावा कि std :: stable_sort वास्तव में कितना धीमा है और दूसरा मर्ज सॉर्ट कार्यान्वयन बहुत बेहतर होगा क्योंकि सबसे अच्छा और सबसे खराब मामला n लॉग n है जबकि std :: stable_sort जैसा है ... n log n^2 या कुछ ऐसा गूंगा है। इसलिए, मैं उस पते के उत्तर को अद्यतन करता हूं, जो ज्यादातर। यदि आप करते हैं तो मैं आपको वोट दूंगा। या मैं सिद्धांत को अपने उत्तर में समझाऊंगा ... –

+0

@OrgnlDave: ऐसा नहीं। यदि आप दो फ़ील्ड पर * अलग से * सॉर्ट करते हैं तो आपको एक स्थिर प्रकार * केवल * की आवश्यकता होती है। यानी, आप पहले तिथि के अनुसार क्रमबद्ध करते हैं, फिर नाम से अलग से क्रमबद्ध करें, और तारीखों को क्रम में रहने का इरादा रखें। यह एक बार में दोनों तुलना कर रहा है, इसलिए एक ही प्रकार (जो अस्थिर हो सकता है) दोनों नाम और तारीख द्वारा व्यवस्थित किया जाता है। –

+0

क्षमा करें, लेकिन तुलनित्र एक स्थिर प्रकार प्रदान नहीं करेगा –

0

उस डेटा संरचना को ठीक से ठीक काम करना चाहिए। आपको क्या करना चाहिए ऑपरेटर से कम ओवरराइड करना है, तो आप उन्हें मानचित्र में बस सम्मिलित कर सकते हैं और उन्हें सॉर्ट किया जाएगा। Here is more info on the comparison operators for a map

अद्यतन: आगे प्रतिबिंब पर, मैं एक सेट का उपयोग करता हूं, न कि मानचित्र, क्योंकि मूल्य की कोई आवश्यकता नहीं है। लेकिन यहाँ सबूत यह अभी भी काम करता है

सबूत यह काम करता है:

#include<string> 
#include<map> 
#include<stdio.h> 
#include <sstream> 


using namespace std; 

struct entry { 
    int m_id_number; 
    string m_name1; 
    int m_date; 
    string m_name2; 

    entry( int id_number, string name1, int date, string name2) : 
     m_id_number(id_number), 
     m_name1(name1), 
     m_date(date), 
     m_name2(name2) 
    { 

    } 

    // Add this as a member function to `entry`. 
    bool operator<(entry const &other) const { 
     if (m_name1 < other.m_name1) 
      return true; 
     if (m_name2 < other.m_name2) 
      return true; 
     if (m_date < other.m_date) 
      return true; 
     return false; 
    } 

    string toString() const 
    { 
     string returnValue; 

     stringstream out; 
     string dateAsString; 

     out << m_date; 
     dateAsString = out.str(); 

     returnValue = m_name1 + " " + m_name2 + " " + dateAsString; 

     return returnValue; 
    } 
}; 


int main(int argc, char *argv[]) 
{ 
    string names1[] = {"Dave", "John", "Mark", "Chris", "Todd"}; 
    string names2[] = {"A", "B", "C", "D", "E", "F", "G"}; 

    std::map<entry, int> mymap; 
    for(int x = 0; x < 100; ++x) 
    { 
     mymap.insert(pair<entry, int>(entry(0, names1[x%5], x, names2[x%7]), 0)); 
    } 

    std::map<entry, int>::iterator it = mymap.begin(); 
    for(; it != mymap.end() ;++it) 
    { 
     printf("%s\n ", it->first.toString().c_str()); 
    } 
    return 0; 
} 
+0

std :: मानचित्र स्थिर प्रकार होने की गारंटी नहीं है –

+1

मैं कई प्रकार से नहीं कह रहा हूं। मैं कह रहा हूं कि एक तरह से करें जहां ऑपरेटर वजन से कम नाम पहले तारीख है। दो प्रकार क्यों करते हैं जब एक (थोड़ा अधिक जटिल) करेगा? –

+0

@OrgnlDave सबूत के साथ अद्यतन यह पर्याप्त है। –

0

वास्तव में आप समारोह वस्तु का उपयोग अपने छँटाई मापदंड

लागू करने के लिए कर सकते हैं लगता है कि आप सेट में प्रविष्टियों स्टोर करने के लिए चाहते हैं

//EntrySortCriteria.h 
class EntrySortCriteria 
{ 
    bool operator(const entry &e1, const entry &e2) const 
    { 
     return e1.name1 < e2.name1 || 
       (!(e1.name1 < e2.name1) && e1.date < e2.date)) 
    } 
} 

//main.cc 
#include <iostream> 
#include "EntrySortCriteria.h" 

using namespace std; 
int main(int argc, char **argv) 
{ 

    set<entry, EntrySortCriteria> entrySet; 
    //then you can put entries into this set, 
    //they will be sorted automatically according to your criteria 
    //syntax of set: 
    //entrySet.insert(newEntry); 
    //where newEntry is a object of your entry type  
} 
संबंधित मुद्दे