özel bir karşılaştırıcı ile c ++ 'da bir öncelikli kuyruğun bildirilmesi


88

Karşılaştırıcı işlevi olarak (düğüm sınıfının dışında olan) priority_queue of nodeskullanarak a bildirmeye çalışıyorum bool Compare(Node a, Node b).

Şu anda sahip olduğum şey:

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

Nedense alıyorum Error: "Compare" is not a type name

Beyanı olarak değiştirme priority_queue <Node, vector<Node>, bool Compare>

bana verir Error: expected a '>'

Ben de denedim:

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

Nasıl doğru bir şekilde beyan etmeliyim priority_queue?

Yanıtlar:


114

Bir sınıf Comparetanımlamalı operator()ve bunun için şu şekilde aşırı yüklemelisiniz :

class Foo
{

};

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

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

Ya da bazı nedenlerden dolayı sınıf yapamıyorsanız, bunun std::functioniçin kullanabilirsiniz :

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
Mükemmel, tam aradığım şey. Ayrı bir ders yapmayı hiç düşünmedim. İlk örnek daha iyi bir stil olarak kabul edilir mi?
— Steven Morad

2
@StevenMorad, sınıfı aşırı yüklenmiş olarak kullanmayı tercih ediyorum operator(), daha basit görünüyor.
— awesoon

2
@soon Neden operatörü () aşırı yüklüyoruz? Bu, öncelikli kuyruğun dahili olarak nasıl uygulandığıyla bağlantılı mı? aşırı yükleme> veya <sezgisel olarak mantıklı, ancak () operatör çok fazla değil
— Piyush

2
@Piyush, soru, özel bir karşılaştırıcıyı pritority_queue. operator<Dahili std::lesskarşılaştırıcıyı aşırı yüklemek ve kullanmak mümkündür , ancak soruya göre bool Compare(Node a, Node b)sınıfın dışında beyan edilen Node.
— awesoon

3
Ben sözdizimi hatırlayamıyorum şimdi muhtemelen 50 kez gibi, bu cevaba keep coming back
— Rockstar5645

52

Kabul edilen cevap, std::functionkarşılaştırıcı olarak bir sınıf veya a kullanmanız gerektiğine inanmanızı sağlar . Bu doğru değil! Cute_ptr yanıtının gösterdiği gibi, kurucuya bir işlev göstericisi geçirebilirsiniz. Ancak, bunu yapmak için sözdizimi burada gösterilenden çok daha basittir:

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

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

Yani, işlevin türünü açıkça kodlamanıza gerek yoktur, bunu sizin için derleyicinin yapmasına izin verebilirsiniz decltype.

Karşılaştırıcı bir lambda ise bu çok kullanışlıdır. Lambda türünü kullanmaktan başka bir şekilde belirleyemezsiniz decltype. Örneğin:

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

2
Bu harika, merak ediyorum burada olası tuzaklar (sorunlar) var mı? Bu cevabın daha fazla görünürlük ve tartışma aldığını görmek isterim.
— Apollys,

1
@Apollys: Bu yöntemi düzenli olarak kullanıyorum (genellikle Comparebir lambda, bunun için bildirim yazmak imkansızdır), herhangi bir tuzak bilmiyorum.
— Cris Luengo

Bunu bir lambda işlevi için yapacak olsaydınız, lambda işlevinin gövdesini nereye koyardınız? Bunu bir değişkende saklamak istiyorsunuz fönceden ve daha sonra değiştirmek Compareile f?
— Eric Auld

@EricAuld: Evet, Compareburada olduğu gibi bir lambda işlevi olabilir auto Compare = [](){};. Ama decltype(Compare)bunun yerine kullanmanız gerekiyor decltype(&Compare).
— Cris Luengo

Merhaba Chris, bu harika, öncelikli sıra için decltype ile kullanılacak bir format arıyordum ve bir sınıf bildirmeden mükemmel cevabı verdin! Teşekkürler!
— Amanda Wang

17

Üçüncü şablon parametresi operator()(Node,Node)aşırı yüklenmiş bir sınıf olmalıdır . Yani şu şekilde bir sınıf oluşturmanız gerekecek:

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

Ve sonra bu sınıfı aşağıdaki gibi üçüncü şablon parametresi olarak kullanacaksınız:

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

14
Operatör yöntemi halka açık olmalıdır.
— knezi

1
Üçüncü şablonun bir sınıf olması gerekmez. Bir işlevin türü olabilir.
— Cris Luengo

1
Cpluplus'a göre : Bu bir işlev işaretçisi veya işlev nesnesi olabilir
— Benav

10

Sorunuzu doğrudan cevaplamak:

priority_queueKullanarak bir düğüm bildirmeye çalışıyorumbool Compare(Node a, Node b) as the comparator function

Şu anda sahip olduğum şey:

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

Bazı nedenlerden dolayı Hata alıyorum:

"Compare" is not a type name

Derleyici size tam olarak neyin yanlış olduğunu söylüyor: Comparebir tür adı değil, iki alan Nodesve bir bool.
İhtiyacınız olan şey, fonksiyon işaretçisi tipini belirlemektir:
std::priority_queue<Node, std::vector<Node>, bool (*)(Node, Node)> openSet(Compare)


Bu tam olarak öncelikli sıra bildiriminde bir işlev vermek için aradığım şey, teşekkürler!
— Amanda Wang

6

Bir lambda işlevi de kullanılabilir.

auto Compare = [](Node &a, Node &b) { //compare };
std::priority_queue<Node, std::vector<Node>, decltype(Compare)> openset(Compare);

6

Önce karşılaştırmayı tanımlamalısınız. Bunu yapmanın 3 yolu vardır:

  1. sınıf kullan
  2. yapı kullanın (sınıfla aynıdır)
  3. lambda işlevini kullanın.

Sınıfı / yapıyı kullanmak kolaydır çünkü bildirmek kolaydır, sadece bu kod satırını çalıştırma kodunuzun üzerine yazın

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)
   }
};

Arama kodu:

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

Noktaya kadar @shivam Mishra.
— fight_club

3

Bunun herkese yardımcı olması durumunda:

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

0

struct'u tercih eder ve std :: daha büyüklerin yaptığı şeydir

struct Compare {
  bool operator()(Node const&, Node &) {}
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.