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

Дефиниция и приложения
Ключове, приоритети и релации на пълна наредба
Операции на приоритетна опашка АТД и приложения
Сортиране с приоритетна опашка
Композиции и компаратори
Реализация на приоритетна опашка АТД с редица АТД
Сортиране  чрез избор (Selection-Sort)
Сортиране чрез вмъкване (Insertion-Sort)


Приоритетна опашка

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

Примери:
Приоритетът обикновено е числова стойност - по-малка стойност означава по-висок приоритет.

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

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

Операции на приоритетна опашка АТД и приложения

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

Сортиране с приоритетна опашка

Ще използваме приоритетна опашка за сортиране на множество от сравними елементи:
-- Добавяме елементите един по един със серия от insertItem(e,e) операции.
--
Премахваме елементите в нарастващ ред със серия от 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 }

Времето за работа на алгоритъма се определя от времето за изпълнение на операциите insertItem(e,e) и removeMin(), което зависи от реализацията на приоритетната опашка.


Пример за действието на функциите на приоритетната опашка АТД

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


Композиции и компаратори(comparators)

Все още има два важни въпроса, които са неопределени до този момент:
    -- Как да се пазят връзките между елементите и техните ключове?
    -- Как да се сравняват ключовете, за да се определи най-малък ключ?

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

item.cpp

Компаратор-шаблон
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)

comp.cpp

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

Реализация е несортирана редица Реализация със сортирана редица 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)
    ()
    Select-sort with Gypsy folk dance

    Сортиране чрез вмъкване (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)
    ()
    Insert-sort with Romanian folk dance