वस्तुओं के लिए प्राथमिकता कतार STL का उपयोग कैसे करें?


80
class Person
{
public:
    int age;
};

मैं कक्षा व्यक्ति की वस्तुओं को प्राथमिकता कतार में संग्रहीत करना चाहता हूं।

priority_queue< Person, vector<Person>, ??? >

मुझे लगता है कि मुझे तुलनात्मक चीज़ के लिए एक वर्ग को परिभाषित करने की आवश्यकता है, लेकिन मुझे इसके बारे में निश्चित नहीं है।

इसके अलावा, जब हम लिखते हैं,

priority_queue< int, vector<int>, greater<int> > 

बड़ा काम कैसे करता है?


जवाबों:


110

आपको Personइस मामले में कतार में संग्रहीत प्रकार के लिए एक वैध सख्त कमजोर आदेश देने की आवश्यकता है । डिफ़ॉल्ट का उपयोग करना है std::less<T>, जो कुछ के बराबर हल करता है operator<। इस पर निर्भर करता है कि यह स्वयं का संग्रहित प्रकार है। इसलिए अगर आप को लागू करना था

bool operator<(const Person& lhs, const Person& rhs); 

यह बिना किसी और बदलाव के काम करना चाहिए। कार्यान्वयन हो सकता है

bool operator<(const Person& lhs, const Person& rhs)
{
  return lhs.age < rhs.age;
}

यदि प्रकार में एक प्राकृतिक "तुलना में कम" नहीं है, तो यह डिफ़ॉल्ट के बजाय अपने स्वयं के विधेय प्रदान करने के लिए अधिक समझ में आता है std::less<Person>। उदाहरण के लिए,

struct LessThanByAge
{
  bool operator()(const Person& lhs, const Person& rhs) const
  {
    return lhs.age < rhs.age;
  }
};

फिर इस तरह से कतार को तुरंत चालू करें:

std::priority_queue<Person, std::vector<Person>, LessThanByAge> pq;

std::greater<Person>तुलनित्र के रूप में उपयोग के संबंध में , यह समतुल्य का उपयोग करेगा operator>और प्राथमिकता उल्टे WRT डिफ़ॉल्ट मामले के साथ एक कतार बनाने का प्रभाव होगा। इसके लिए operator>दो Personउदाहरणों पर काम कर सकता है ।


7
जबकि यह उत्तर सही है, मुझे operator<यहाँ का उपयोग नापसंद है। operator<एक प्रकार के लिए डिफ़ॉल्ट तुलना को लागू करता है, जो, मेरे अनुभव में, शायद ही कभी आप चाहते हैं। मुझे लगता है कि माइक अपने जवाब में जिस दृष्टिकोण का वर्णन करता है वह लगभग हमेशा बेहतर होता है।
ब्योर्न पोलेक्स

1
@ BjörnPollex सहमत हुए। मैं उस बारे में कुछ जोड़ रहा था। केवल एक डेटा सदस्य वाली कक्षा में, ऑपरेटर को समझ में आ सकता है।
जुआनकोपंजा

ध्यान देने योग्य: लागू करने bool YourClass::operator <(const YourClass&) constसे डिफ़ॉल्ट तुलनित्र के पारदर्शी उपयोग की भी अनुमति होगी std::less<T>। उतने लचीले नहीं, लेकिन कार्यात्मक जब आपको वह सब चाहिए। (और +1)।
व्हेजक्राइग

जवाब के लिए धन्यवाद। मैं '<' ऑपरेटर को ओवरलोड कर सकता हूं, भले ही कक्षा में कई सदस्य हों, सही?
user2441151

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

50

आप एक तुलनित्र वर्ग लिखेंगे, उदाहरण के लिए:

struct CompareAge {
    bool operator()(Person const & p1, Person const & p2) {
        // return "true" if "p1" is ordered before "p2", for example:
        return p1.age < p2.age;
    }
};

और तुलनित्र तर्क के रूप में उपयोग करें:

priority_queue<Person, vector<Person>, CompareAge>

उपयोग greaterकरने से डिफ़ॉल्ट के विपरीत क्रम मिलता है less, जिसका अर्थ है कि कतार आपको उच्चतम के बजाय न्यूनतम मूल्य देगी।


1
तुलनित्र वर्गों के बजाय "तुलनित्र वस्तुओं" को पारित करना संभव है? (इसे
परमाग्रीज

1
@castarco हाँ, आप एक निर्माता के रूप में एक विशिष्ट तुलनित्र वस्तु पास कर सकते हैं।
माइक सीमोर

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

20

एक प्राथमिकता कतार एक सार डेटा प्रकार है जो एक कंटेनर के विचार को कैप्चर करता है जिसके तत्वों में "प्राथमिकताएं" उनसे जुड़ी होती हैं। सर्वोच्च प्राथमिकता का एक तत्व हमेशा कतार के सामने दिखाई देता है। यदि वह तत्व हटा दिया जाता है, तो अगला सर्वोच्च प्राथमिकता तत्व सामने वाले को आगे बढ़ाता है।

C ++ मानक पुस्तकालय निम्नलिखित कार्यों के साथ एक वर्ग टेम्पलेट प्राथमिकता_ चक्र को परिभाषित करता है:

धक्का : एक तत्व को पवित्रता कतार में डालें।

शीर्ष : वापसी (इसे हटाए बिना) प्राथमिकता कतार से सर्वोच्च प्राथमिकता वाला तत्व।

पॉप : प्राथमिकता कतार से एक सर्वोच्च प्राथमिकता तत्व निकालें।

आकार : प्राथमिकता कतार में तत्वों की संख्या लौटाएं।

खाली : प्राथमिकता कतार के खाली होने या न होने के अनुसार सही या गलत होने पर लौटें।

निम्न कोड स्निपेट दिखाता है कि दो प्राथमिकता वाले कतारों का निर्माण कैसे किया जाता है, एक जिसमें पूर्णांक हो सकते हैं और एक अन्य जिसमें वर्ण तार हो सकते हैं:

#include <queue>

priority_queue<int> q1;
priority_queue<string> q2;

निम्नलिखित प्राथमिकता कतार उपयोग का एक उदाहरण है:

#include <string>
#include <queue>
#include <iostream>

using namespace std;  // This is to make available the names of things defined in the standard library.

int main()
{
    piority_queue<string> pq; // Creates a priority queue pq to store strings, and initializes the queue to be empty.

    pq.push("the quick");
    pq.push("fox");
    pq.push("jumped over");
    pq.push("the lazy dog");

    // The strings are ordered inside the priority queue in lexicographic (dictionary) order:
    // "fox", "jumped over", "the lazy dog", "the quick"
    //  The lowest priority string is "fox", and the highest priority string is "the quick"

    while (!pq.empty()) {
       cout << pq.top() << endl;  // Print highest priority string
       pq.pop();                    // Remmove highest priority string
    }

    return 0;
}

इस कार्यक्रम का आउटपुट है:

the quick
the lazy dog
jumped over
fox

चूँकि एक कतार एक प्राथमिकता अनुशासन का पालन करती है, तार उच्चतम से सबसे कम प्राथमिकता तक मुद्रित होते हैं।

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

struct Time {
    int h; 
    int m; 
    int s;
};

class CompareTime {
    public:
    bool operator()(Time& t1, Time& t2) // Returns true if t1 is earlier than t2
    {
       if (t1.h < t2.h) return true;
       if (t1.h == t2.h && t1.m < t2.m) return true;
       if (t1.h == t2.h && t1.m == t2.m && t1.s < t2.s) return true;
       return false;
    }
}

उपरोक्त तुलना कसौटी के अनुसार समय को स्टोर करने के लिए एक प्राथमिकता कतार निम्नानुसार परिभाषित की जाएगी:

priority_queue<Time, vector<Time>, CompareTime> pq;

Here is a complete program:

#include <iostream>
#include <queue>
#include <iomanip>

using namespace std;

struct Time {
    int h; // >= 0
    int m; // 0-59
    int s; // 0-59
};

class CompareTime {
public:
    bool operator()(Time& t1, Time& t2)
    {
       if (t1.h < t2.h) return true;
       if (t1.h == t2.h && t1.m < t2.m) return true;
       if (t1.h == t2.h && t1.m == t2.m && t1.s < t2.s) return true;
       return false;
    }
};

int main()
{
    priority_queue<Time, vector<Time>, CompareTime> pq;

    // Array of 4 time objects:

    Time t[4] = { {3, 2, 40}, {3, 2, 26}, {5, 16, 13}, {5, 14, 20}};

    for (int i = 0; i < 4; ++i)
       pq.push(t[i]);

    while (! pq.empty()) {
       Time t2 = pq.top();
       cout << setw(3) << t2.h << " " << setw(3) << t2.m << " " <<
       setw(3) << t2.s << endl;
       pq.pop();
    }

    return 0;
}

कार्यक्रम नवीनतम से जल्द से जल्द प्रिंट करता है:

5  16  13
5  14  20
3   2  40
3   2  26

यदि हम चाहते थे कि जल्द से जल्द सर्वोच्च प्राथमिकता हो, तो हम इस तरह की तुलना को फिर से परिभाषित करेंगे:

class CompareTime {
public:
    bool operator()(Time& t1, Time& t2) // t2 has highest prio than t1 if t2 is earlier than t1
    {
       if (t2.h < t1.h) return true;
       if (t2.h == t1.h && t2.m < t1.m) return true;
       if (t2.h == t1.h && t2.m == t1.m && t2.s < t1.s) return true;
       return false;
    }
};

1
मेरे पास एक सवाल है, अगर हो सकता है। प्रायोरिटी_क्यू <टाइम, वेक्टर <टाइम>, तुलना टाइम> पीक्यू; । दूसरा पैरामीटर, वेक्टर <Time> क्यों आवश्यक है? मैंने इसे कोड के कई स्निपेट्स में देखा है लेकिन मैं इसे समझ नहीं पाया।
बारबर्डॉरल जूल

अरे नू ... लोमड़ी भूरी नहीं है और गैर-भूरी लोमड़ी ने आलसी कुत्ते के ऊपर छलांग (छलांग) लगाई। :-(
साइबर_राज

3
पहले स्निपेट में pq.front () pq.top () नहीं होना चाहिए?
कोडिंग

4

इस कोड की मदद कर सकते हैं ..

#include <bits/stdc++.h>
using namespace std;    

class node{
public:
    int age;
    string name;
    node(int a, string b){
        age = a;
        name = b;
    }
};

bool operator<(const node& a, const node& b) {

    node temp1=a,temp2=b;
    if(a.age != b.age)
        return a.age > b.age;
    else{
        return temp1.name.append(temp2.name) > temp2.name.append(temp1.name);
    }
}

int main(){
    priority_queue<node> pq;
    node b(23,"prashantandsoon..");
    node a(22,"prashant");
    node c(22,"prashantonly");
    pq.push(b);
    pq.push(a);
    pq.push(c);

    int size = pq.size();
    for (int i = 0; i < size; ++i)
    {
        cout<<pq.top().age<<" "<<pq.top().name<<"\n";
        pq.pop();
    }
}

आउटपुट:

22 prashantonly
22 prashant
23 prashantandsoon..

0

हम उपयोगकर्ता परिभाषित तुलनित्र को परिभाषित कर सकते हैं: नीचे दिया गया कोड आपके लिए मददगार हो सकता है।

सांकेतिक टुकड़ा :

#include<bits/stdc++.h>
using namespace std;

struct man
{
  string name;
  int priority; 
};

class comparator
{
 public:
   bool operator()(const man& a, const man& b)
   {
        return a.priority<b.priority;
   }
};

int main()
{
   man arr[5];
   priority_queue<man, vector<man>, comparator> pq;

   for(int i=0; i<3; i++)
   {
     cin>>arr[i].name>>arr[i].priority;
     pq.push(arr[i]);
   }

   while (!pq.empty())
   {
     cout<<pq.top().name<<" "<<pq.top().priority;
     pq.pop();
     cout<<endl;
   }
   return 0;
}

इनपुट:

बैटमैन 2
गोकू 9
मारियो 4

उत्पादन

गोकू ९
मारियो ४
बैटमैन २

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.