it-swarm.com.de

Wie verwende ich die Prioritätswarteschlange für Objekte?

class Person
{
public:
    int age;
};

Ich möchte Objekte der Klasse Person in einer Prioritätswarteschlange speichern.

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

Ich denke, ich muss eine Klasse für die Vergleichssache definieren, bin mir aber nicht sicher.

Auch wenn wir schreiben,

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

Wie funktioniert die größere Arbeit?

64
user2441151

Für den in der Warteschlange gespeicherten Typ muss Person ein gültiger Vergleich der strengen Reihenfolge der schwachen Reihenfolge angegeben werden. Die Standardeinstellung ist std::less<T>, was sich in etwas äquivalent zu operator< auflöst. Dies setzt voraus, dass der eigene gespeicherte Typ einen hat. Also wenn du implementieren würdest

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

es sollte ohne weitere Änderungen funktionieren. Die Umsetzung könnte sein

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

Wenn der Typ keinen natürlichen Vergleich mit "weniger als" hat, wäre es sinnvoller, anstelle des Standardwerts std::less<Person> ein eigenes Prädikat anzugeben. Zum Beispiel,

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

dann instanziieren Sie die Warteschlange folgendermaßen:

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

In Bezug auf die Verwendung von std::greater<Person> als Vergleicher würde dies das Äquivalent von operator> verwenden und dazu führen, dass eine Warteschlange mit dem invertierten WRT-Standardwert erstellt wird. Es müsste ein operator> vorhanden sein, der zwei Instanzen Person ausführen kann.

98
juanchopanza

Sie würden beispielsweise eine Komparator-Klasse schreiben:

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

und verwende das als Vergleichsargument:

priority_queue<Person, vector<Person>, CompareAge>

Die Verwendung von greater gibt die entgegengesetzte Reihenfolge zum Standard less vor, was bedeutet, dass die Warteschlange Ihnen den niedrigsten Wert und nicht den höchsten Wert gibt.

42
Mike Seymour

Eine Prioritätswarteschlange ist ein abstrakter Datentyp, der die Idee eines Containers erfasst, an dessen Elemente "Prioritäten" angehängt sind. Ein Element mit der höchsten Priorität wird immer vor der Warteschlange angezeigt. Wenn dieses Element entfernt wird, rückt das nächsthöhere Prioritätselement nach vorne vor. 

Die C++ - Standardbibliothek definiert eine Klassenvorlage priority_queue mit den folgenden Operationen:

Push : Fügt ein Element in die Prioritätswarteschlange ein.

top : Gibt (ohne es zu entfernen) ein Element mit der höchsten Priorität aus der Prioritätswarteschlange zurück.

pop : Entfernt ein Element mit der höchsten Priorität aus der Prioritätswarteschlange.

size : Gibt die Anzahl der Elemente in der Prioritätswarteschlange zurück.

empty : Gibt true oder false zurück, je nachdem, ob die Prioritätswarteschlange leer ist oder nicht.

Der folgende Codeausschnitt zeigt, wie zwei Prioritätswarteschlangen erstellt werden, von denen eine Ganzzahlen und eine andere Zeichenfolgen enthalten kann:

#include <queue>

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

Das folgende Beispiel zeigt die Verwendung von Prioritätswarteschlangen:

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

Die Ausgabe dieses Programms ist:

the quick
the lazy dog
jumped over
fox

Da eine Warteschlange einer Prioritätsdisziplin folgt, werden die Zeichenfolgen von der höchsten zur niedrigsten Priorität gedruckt.

Manchmal muss eine Prioritätswarteschlange erstellt werden, die benutzerdefinierte Objekte enthält. In diesem Fall muss die Prioritätswarteschlange das Vergleichskriterium kennen, mit dem bestimmt wird, welche Objekte die höchste Priorität haben. Dies geschieht mittels eines Funktionsobjekts, das zu einer Klasse gehört, die den Operator () überlastet. Überladen () fungiert als <zur Festlegung von Prioritäten. Angenommen, wir möchten eine Prioritätswarteschlange zum Speichern von Zeitobjekten erstellen. Ein Zeitobjekt hat drei Felder: Stunden, Minuten, Sekunden:

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

Eine Prioritätswarteschlange zum Speichern von Zeiten, die dem obigen Vergleichskriterium entsprechen, würde wie folgt definiert:

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

Das Programm druckt die Zeiten von spät bis früh:

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

Wenn wir wollten, dass die frühesten Zeiten die höchste Priorität haben, würden wir CompareTime wie folgt neu definieren:

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

Dieser Code kann hilfreich sein ..

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

Ausgabe: 

22 prashantonly
22 prashant
23 prashantandsoon..
2
enig123

Wir können einen benutzerdefinierten Vergleicher definieren: Der untenstehende Code kann für Sie hilfreich sein.

Code-Auszug :

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

Eingabe:

batman 2
Goku 9
Mario 4 

Ausgabe  

goku 9
Mario 4
Batman 2 

0
rashedcs