एक कस्टम तुलनित्र के साथ c ++ में प्रायोरिटी_क्व्यू घोषित करना


88

मैं तुलनित्र फ़ंक्शन (जो नोड वर्ग के बाहर है) priority_queue of nodesका उपयोग करके, एक घोषित करने की कोशिश कर रहा हूं bool Compare(Node a, Node b)

वर्तमान में मेरे पास क्या है:

priority_queue<Node, vector<Node>, Compare> openSet;

किसी कारण से, मुझे मिल रहा है Error: "Compare" is not a type name

के लिए घोषणा को बदलना priority_queue <Node, vector<Node>, bool Compare>

मुझे देता है Error: expected a '>'

मैंने भी कोशिश की है:

priority_queue<Node, vector<Node>, Compare()> openSet;
priority_queue<Node, vector<Node>, bool Compare()> openSet;
priority_queue<Node, vector<Node>, Compare<Node, Node>> openSet; 

मुझे अपनी घोषणा सही ढंग से कैसे करनी चाहिए priority_queue?

जवाबों:


113

आपको एक वर्ग घोषित करना चाहिए Compareऔर operator()इस तरह से इसके लिए अधिभार देना चाहिए :

class Foo
{

};

class Compare
{
public:
    bool operator() (Foo, Foo)
    {
        return true;
    }
};

int main()
{
    std::priority_queue<Foo, std::vector<Foo>, Compare> pq;
    return 0;
}

या, यदि आप कुछ कारणों से इसे कक्षा के रूप में नहीं बना सकते हैं, तो आप इसके लिए उपयोग कर सकते हैं std::function:

class Foo
{

};

bool Compare(Foo, Foo)
{
    return true;
}

int main()
{
    std::priority_queue<Foo, std::vector<Foo>, std::function<bool(Foo, Foo)>> pq(Compare);
    return 0;
}

1
मुझे इसकी ही चाहत थी। मैंने कभी अलग वर्ग बनाने के लिए नहीं सोचा था। क्या पहले उदाहरण को बेहतर शैली माना जाएगा?
स्टीवन मोराद

2
@StevenMorad, मैं अतिभारित के साथ वर्ग का उपयोग करना पसंद करता हूं operator(), यह सरल दिखता है।
awesoon

1
@soon हम ऑपरेटर को ओवरलोड क्यों करते हैं ()? क्या यह इस बात से जुड़ा हुआ है कि कैसे प्राथमिकता_ आंतरिक रूप से लागू की जाती है? ओवरलोडिंग> या <सहज रूप से समझ में आता है, लेकिन () ऑपरेटर इतना नहीं
पीयूष

2
@ पीयूष, सवाल एक कस्टम तुलनित्र को पास करने के बारे में है pritority_queue। प्रश्न के अनुसार, operator<अंतर्निहित std::lessतुलनित्र को अधिभार और उपयोग करना संभव है , हालांकि, bool Compare(Node a, Node b)कक्षा के बाहर घोषित किया Nodeगया है।
awesoon

3
मैं इस उत्तर पर वापस आता रहता हूं, शायद अब 50 बार की तरह, मैं वाक्यविन्यास को कभी भी याद नहीं कर सकता
रॉकस्टार

52

स्वीकृत उत्तर आपको विश्वास दिलाता है कि आपको एक वर्ग या एक std::functionतुलनित्र का उपयोग करना चाहिए । यह सच नहीं है! जैसा कि क्यूट_प्रेट का उत्तर दिखाता है, आप कंस्ट्रक्टर को फ़ंक्शन पॉइंटर पास कर सकते हैं। हालाँकि, ऐसा करने के लिए सिंटैक्स वहाँ दिखाए गए की तुलना में बहुत सरल है:

class Node;
bool Compare(Node a, Node b);

std::priority_queue<Node, std::vector<Node>, decltype(&Compare)> openSet(Compare);

यही है, फ़ंक्शन के प्रकार को स्पष्ट रूप से एन्कोड करने की कोई आवश्यकता नहीं है, आप कंपाइलर का उपयोग करने के लिए कर सकते हैं decltype

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

auto compare = [](Node a, Node b) { return a.foo < b.foo; }
std::priority_queue<Node, std::vector<Node>, decltype(compare)> openSet(compare);

2
यह शानदार है, मुझे आश्चर्य है कि अगर यहां कोई संभावित जाल (मुद्दे) हैं। इस उत्तर को और अधिक दृश्यता और चर्चा प्राप्त करना पसंद करेंगे।
अपोलिस, मोनिका

1
@ सहायक: मैं नियमित रूप से इस विधि का उपयोग करता हूं (आमतौर Compareपर एक लंबोदर है , जिसके लिए घोषणा लिखना असंभव है), मुझे किसी भी जाल का पता नहीं है।
क्राइस लुआंगो

यदि आप एक मेमने के कार्य के लिए ऐसा करते हैं, तो आप भेड़ के बच्चे के शरीर को कहाँ रखेंगे? आप इसे एक चर में संग्रहीत कर सकते हैं fपहले से और उसके बाद की जगह Compareके साथ f?
एरिक औल

@EricAuld: हाँ, Compareवहाँ एक लंबो फ़ंक्शन हो सकता है, जैसा कि अंदर है auto Compare = [](){};। लेकिन आपको decltype(Compare)इसके बजाय उपयोग करने की आवश्यकता है decltype(&Compare)
संकट लुएंगो

हाय क्रिस, यह बहुत अच्छा है, मैं कुछ प्रारूप की तलाश कर रहा था प्राथमिकता के लिए घोषणापत्र के साथ उपयोग करें_क्यू और एक वर्ग घोषित किए बिना, आपने सही जवाब दिया! धन्यवाद!
अमांडा वांग

17

तीसरा टेम्प्लेट पैरामीटर एक ऐसा वर्ग होना चाहिए जिसने operator()(Node,Node)ओवरलोड किया हो। तो आपको इस तरह से एक क्लास बनाना होगा:

class ComparisonClass {
    bool operator() (Node, Node) {
        //comparison code here
    }
};

और फिर आप इस वर्ग को इस तरह तीसरे टेम्पलेट पैरामीटर के रूप में उपयोग करेंगे:

priority_queue<Node, vector<Node>, ComparisonClass> q;

14
ऑपरेटर विधि सार्वजनिक होनी चाहिए।
knezi

1
तीसरे टेम्पलेट को एक वर्ग होने की आवश्यकता नहीं है। यह एक फ़ंक्शन का प्रकार हो सकता है।
संकट लुएंगो

1
Cpluplus के अनुसार : यह एक फंक्शन पॉइंटर या फंक्शन ऑब्जेक्ट हो सकता है
Benav

9

सीधे अपने प्रश्न का उत्तर देना:

मैं एक priority_queueनोड की घोषणा करने की कोशिश कर रहा हूँ , का उपयोग करते हुएbool Compare(Node a, Node b) as the comparator function

वर्तमान में मेरे पास क्या है:

priority_queue<Node, vector<Node>, Compare> openSet;

किसी कारण से, मुझे त्रुटि मिल रही है:

"Compare" is not a type name

संकलक आपको बता रहा है कि वास्तव में क्या गलत है: Compareएक प्रकार का नाम नहीं है, लेकिन एक फ़ंक्शन का एक उदाहरण जो दो लेता है Nodesऔर एक रिटर्न देता है bool
फ़ंक्शन पॉइंटर प्रकार निर्दिष्ट करने के लिए आपको क्या चाहिए:
std::priority_queue<Node, std::vector<Node>, bool (*)(Node, Node)> openSet(Compare)


यह वही है जो मैं देख रहा हूं कि प्राथमिकता में एक समारोह देने की घोषणा की है, धन्यवाद!
अमांडा वैंग


6

आपको पहले तुलना को परिभाषित करना होगा। ऐसा करने के 3 तरीके हैं:

  1. वर्ग का उपयोग करें
  2. संरचना का उपयोग करें (जो वर्ग के समान है)
  3. लैम्ब्डा फ़ंक्शन का उपयोग करें।

कक्षा / संरचना का उपयोग करना आसान है क्योंकि घोषित करने के लिए आसान है बस अपने निष्पादन कोड के ऊपर कोड की इस पंक्ति को लिखें

struct compare{
  public:
  bool operator()(Node& a,Node& b) // overloading both operators 
  {
      return a.w < b.w: // if you want increasing order;(i.e increasing for minPQ)
      return a.w > b.w // if you want reverse of default order;(i.e decreasing for minPQ)
   }
};

कॉलिंग कोड:

priority_queue<Node,vector<Node>,compare> pq;

बिंदु @ शशिम मिश्रा को।
fight_club

3

मामले में यह किसी को भी मदद करता है:

static bool myFunction(Node& p1, Node& p2) {}
priority_queue <Node, vector<Node>, function<bool(Node&, Node&)>> pq1(myFunction);

0

संरचना पसंद करते हैं, और यह क्या std :: अधिक से अधिक है

struct Compare {
  bool operator()(Node const&, Node &) {}
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.