Приоритетна опашка - първа част

Приоритетна опашка е АТД за съхраняване на съвкупност от обекти (items) с приоритети, която поддържа вмъкване и премахване на обект, като премахването става по приоритет, т.е. обектът с първи приоритет се премахва най-напред.
Примери:
Приоритетът обикновено е числова стойност - по-малка стойност означава по-висок приоритет.

Ключове, приоритети и релации на пълна наредба

Ще дефинираме ключ като обект (object), прикачен към някой елемент като специфичен атрибут, който може да бъде използван за идентификация, ранг, или тегло на този елемент.

Сравняване на ключове и пълна наредба

Да предположим, че даден полет е изцяло запълнен един час преди началото на пътуването. Поради възможността за отказване (анулиране), авиокомпанията поддържа приоритетната опашка на чакащите за място пътници. Приоритетът на всеки пътник се определя от стойността на билета, често-пътуващ статут (frequent-flyer status), както от и времето, когато пътникът е поставен в приоритетната опашка. Когато пътник се регистрира като чакащ за място, свързаният с пътника обект се добавя в приоритетната опашка с операция insertItem. Малко преди излитането на самолета, ако станат достъпни места (например, поради отказване в последната минута), авиокомпанията многократно премахва от приоритетната опашка чакащ за място пътник с първи приоритет, като се използва комбинация от minElement() и removeMin() операции и качва този пътник на самолета. 

Сортиране с приоритетна опашка
  1. Добавяме елементите един по един със серия от insertItem(e,e) операции.
  2. Премахваме елементите в нарастващ ред със серия от removeMin() операции.
  • Времето за работа на този метод на сортиране зависи от реализацията на приоритетната опашка АТД.
  • Algorithm PriorityQueueSort(S, P):
    Input: Редица S съдържаща n елемента, за които е дефинирана пълна наредба
        и опашка с приоритети P, която сравнява ключове със същата наредба
    Output: Редица S наредена с тази наредба
    while !S.isEmpty() do
       e <- S.removeFirst()   { премахва елемент e от
    S }
       
    P.insertItem(e,e)         { ключът е самия елемент }
    while !
    P.isEmpty() do
       
    e <- P.minElement()    { взема на-малкия елемент от P }
       
    P.removeMin()               { премахва този елемент от P }
       
    S.insertLast(e)             { добавя елемента към края на S }
    Operation
    Output
    Priority Queue
    insertItem(5,A)
    -
    {(5,A)}
    insertItem(9,C) -
    {(5,A),(9,C)}
    insertItem(3,B) -
    {(3,B),(5,A),(9,C)}
    insertItem(7,D) -
    {(3,B),(5,A),(7,D),(9,C)}
    minElement()
    B
    {(3,B),(5,A),(7,D),(9,C)}
    minKey()
    3
    {(3,B),(5,A),(7,D),(9,C)}
    removeMin()
    -
    {(5,A),(7,D),(9,C)}
    size()
    3
    {(5,A),(7,D),(9,C)}
    minElement()
    A
    {(5,A),(7,D),(9,C)}
    removeMin()
    -
    {(7,D),(9,C)}
    removeMin() -
    {(9,C)}
    removeMin() -
    {}
    removeMin() ERROR
    {}
    isEmpty()
    true
    {}

    Все още има два важни въпроса, които са останали неопределени до този момент:
    Композиции и компаратори

    Композиция-шаблон
    html-7.2 (Item)

    Компаратор
    bool operator<(const Point& p1, const Point& p2)
    { if (p1.getX() == p2.getX()) return p1.getY() < p2.getY();
    else return p1.getX() < p1.getX();
    }
    class LexCompare {
    public:
    int operator()(Point a, Point b) {
    if (a.x < b.x) return –1
    else if (a.x > b.x) return +1;
    else if (a.y < b.y) return –1;
    else if (a.y > b.y) return +1;
    else return 0;
    }
    };
    html-7.3 (Compare)

    Използване на компаратора

    Point p(2.3, 4.5);
    Point q(1.7, 7.3);
    LexCompare lexCompare;
    if (lexCompare(p, q) < 0) cout << “p less than q”;
    else if (lexCompare(p, q) == 0) cout << “p equals q”;
    else if (lexCompare(p, q) > 0) cout << “p greater than q”;
    html-7.4 (Generic)


    Реализация на приоритетна опашка АТД с редица АТД

    Реализация е несортирана редица Реализация със сортирана редица html-7.5 (SSPQ1)
    html-7.6 (SSPQ2)

    [priority.cpp]

    Сравнение на двете реализации

    • Реализация с ненаредена редица
      • Съхранява обектите на приоритетната опашка в редица АТД, (реализирана със свързан списък) в произволен ред.
    • Реализация с наредена редица
      • Съхранява обектите на приоритетната опашка в редица АТД, сортирани по ключ
    • Бързодействие:
      • insertItem отнема време O(1), защото обектът може да се добави в началото или в края на редицата;
      • removeMin, minKey и minElement отнемат време O(n), защото трябва да се обходи цялата редица за да се намери най-малкия ключ.
    • Бързодействие:
      • insertItem отнема време O(n), защото трябва да се намери мястото, където да се вмъкне новия обект;
      • removeMin, minKey и minElement отнемат време O(1), защото най-малкият ключ е в началото на редицата.

    Сортиране  чрез избор (Selection-Sort)
    1. Вмъкване на обектите в приоритетната опашка с n insertItem операции отнема време O(n).
    2. Изваждане на обект в нарастващ ред от приоритетната опашка с n операции removeMin отнема време, пропорционално на 1 + 2 + …+ n.
  • Сортиране чрез избор се изпълнява за време O(n2).

  • Sequence S
    Priority Queue P  (unsorted sequence)
    Input
    (7,4,8,2,5,3,9)
    ()
    Phase 1
    O(n)
    (4,8,2,5,3,9)
    (8,2,5,3,9)
    (2,5,3,9)
    (5,3,9)
    (3,9)
    (9)
    ()
    (7)
    (7,4)
    (7,4,8)
    (7,4,8,2)
    (7,4,8,2,5)
    (7,4,8,2,5,3)
    (7,4,8,2,5,3,9)
    Phase 2
    O(n2)
    (2)
    (2,3)
    (2,3,4)
    (2,3,4,5)
    (2,3,4,5,7)
    (2,3,4,5,7,8)
    (2,3,4,5,7,8,9)
    (7,4,8,5,3,9)
    (7,4,8,5,9)
    (7,8,5,9)
    (7,8,9)
    (8,9)
    (9)
    ()

    Сортиране чрез вмъкване (Insertion-Sort)

    1. Вмъкване на обектите в приоритетната опашка с n операции insertItem отнема време, пропорционално на 1 + 2 + …+ n.
    2. Изваждане на обект (в нарастващ ред) от приоритетната опашка със серия от n removeMin операции отнема време O(n).
  • Сортиране чрез вмъкване се изпълнява за време O(n2).

  • Sequence S
    Priority Queue P  (sorted sequence)
    Input
    (7,4,8,2,5,3,9)
    ()
    Phase 1
    O(n2)
    (4,8,2,5,3,9)
    (8,2,5,3,9)
    (2,5,3,9)
    (5,3,9)
    (3,9)
    (9)
    ()
    (7)
    (4,7)
    (4,7,8)
    (2,4,7,8)
    (2,4,5,7,8)
    (2,3,4,5,7,8)
    (2,3,4,5,7,8,9)
    Phase 2
    O(n)
    (2)
    (2,3)
    (2,3,4)
    (2,3,4,5)
    (2,3,4,5,7)
    (2,3,4,5,7,8)
    (2,3,4,5,7,8,9)
    (3,4,5,7,8,9)
    (4,5,7,8,9)
    (5,7,8,9)
    (7,8,9)
    (8,9)
    (9)
    ()