2012-06-29 34 views
17

Mam wektor, którego chcę użyć do utworzenia sterty. Nie jestem pewien, czy powinienem użyć funkcji make_heap C++ lub umieścić mój wektor w kolejce priorytetowej? Co jest lepsze pod względem wydajności? Kiedy powinienem użyć jednego z drugim?Kiedy należy użyć make_heap vs. Priority Queue?

+1

cóż, jeśli chcesz stertę, powinieneś zrobić z niej kupę. Kolejki priorytetowe to nie wszystkie stosy. Mnożniki mają tendencję do lepszej wydajności. – Wug

Odpowiedz

20

Nie ma różnicy w zakresie wydajności. std::priority_queue to tylko klasa adaptera, która opakowuje kontener i identyczne wywołania funkcji związanych z stertami w klasie. Specyfikacja std::priority_queue otwarcie stwierdza, że.

Budując kolejkę priorytetową opartą na sterty z odsłoniętego std::vector (bezpośrednio wywołując funkcje związane z stertami), pozostaje ona otwarta na możliwość dostępu z zewnątrz, potencjalnie uszkadzając integralność sterty/kolejki. std::priority_queue działa jako bariera ograniczająca dostęp do minimum "kanonicznego": push(), pop(), top() itd. Możesz to zobaczyć jako środek wymuszający samodyscyplinę.

Ponadto, dostosowując interfejs kolejki do "kanonicznego" zestawu operacji, czynisz go jednolitym i wymiennym z innymi wersjami kolejek priorytetów zgodnych z tą samą specyfikacją zewnętrzną.

3

Parametr priority_queue jest (co najmniej normalnie) implementowany jako sterty. W związku z tym prawdziwe pytanie brzmi, czy parametr priority_queue zapewnia to, czego potrzebujesz. Kiedy używasz make_heap, nadal masz dostęp do wszystkich elementów. Kiedy używasz parametru priority_queue, masz tylko kilka operacji, które dają bardzo ograniczony dostęp do elementów (w zasadzie wystarczy wstawić element i usunąć element na początku kolejki).

1

priority_queue nie jest kontenerem. Jest to adapter kontenera, który używa określonego bazowego kontenera, np. vector lub deque i zapewnia określony zestaw metod pracy z danymi. Co więcej, jego implementacja opiera się na algorytmach *_heap.

Na przykład za każdym razem, gdy naciskasz nową wartość na vector, powinieneś zadzwonić pod numer push_heap, aby rozszerzyć zakres uważany za stertę. Jeśli nie używasz priority_queue, możesz rozważyć, powiedzmy, połowę vector jako stertę (std::make_heap(v.begin(), v.begin() + (v.size()/2))), podczas gdy druga połowa będzie taka, jaka jest.

priority_queue Co robi podczas rozmowy push na nim: on popycha nowy element do tyłu bazowego pojemnika i wzywa push_heap zachować właściwości sterty priorytet (ma to znaczenie tylko pierwszy element będzie największa).

Powiedziałbym, że lepiej rozważyć projekt rozwiązania i konkretne wymagania, a nie problemy z wydajnością.

0

Jeśli nie chcesz modyfikować tego wektora, powinieneś użyć kolejki priorytetowej, ponieważ tworzy on oddzielny wektor (wymaga dodatkowej przestrzeni). Co więcej, jest łatwy do wdrożenia. Na przykład, gdy używasz make_heap podczas poppingu elementu, musisz użyć dwóch poleceń, najpierw pop_heap, a następnie pop_back ... ale możesz to zrobić za pomocą tylko jednego polecenia w przypadku kolejki priorytetowej. Podobnie, wpychając element do sterty.
Teraz wydajność obu będzie taka sama, ponieważ kolejka priorytetowa nie jest kontenerem i używa jakiegoś bazowego kontenera jako wektora lub deque, który używa takich samych operacji sterty, jak używane przez operacje make_heap. Więc powinieneś użyć jednego w zależności od twoich wymagań .

Powiązane problemy