Siedzę sobie w domu na urlopie i uskuteczniam to, co lubię najbardziej czyli programuję. Niektórzy lubią wylegiwać się na plaży czekając aż czerniak łaskawie zawita na ich skórę, inni chodzą po zagranicznych targowiskach i pilnują portfela, a ja lubię siedzieć sobie wygodnie przed komputerem cały dzień i dłubać.
Dzisiaj przedmiotem mojego dłubania jest implementacja kolejek priorytetowych w PHP, czyli SplHeap. Cała zabawa polega na tym że dodając nowe elementy do kolejki zawsze mamy je posortowane. Po prostu wrzucamy i tyle — samo się robi :-) Mało tego, podczas wyciągania jakiegoś elementu możemy sobie dodawać nowe i one też zajmują swoje miejsca w hierarchii ważności.
Postawiłem sobie za cel zrobić mechanizm, który będzie mi sortował ciągi znaków. Ponadto ma dać się nim sterować, czy np. liczby mają mieć pierwszeństwo przed literami oraz czy wielkie litery mają mieć pierwszeństwo przed małymi. Powstało coś o ładnej nazwie SpiechuPriorityQueue i SpiechuStringComparator (skromność przede wszystkim).
Najpierw kod klasy kolejki:
class SpiechuPriorityQueue extends SplHeap { private $stringComparator; public function __construct($ignoreCase = false, $numbersAtFront = true) { $this->stringComparator = new SpiechuStringComparator('PL',$ignoreCase,$numbersAtFront); } public function insert($value,$priority = 0) { echo 'Dodaję: ' . $value . '<br/>'; parent::insert($value); } protected function compare($str1,$str2) { return $this->stringComparator->compare($str1, $str2); } public function extract() { $extracted = parent::extract(); echo 'Wyciągam: ' . $extracted . '<br/>'; return $extracted; } }
Mamy tutaj kilka tajemniczych zagrań:
- na etapie tworzenia obiektu kolejki możemy ustalić parametry sortowania,
- całą robotę odwala za nas
SpiechuStringComparator, - nie da się ustalać ręcznie priorytetów w metodzie
insert(ręczne modyfikacje popsułyby nasz mechanizm sortujący), - wymagane jest przesłonięcie metody
compare, którą SplHeap sam sobie wywołuje tworząc hierarchię elementów w środku
Zapewne pojawi się pytanie jak tego używać. Dosyć prosto:
$queue = new SpiechuPriorityQueue(); $queue->insert('ABC'); $queue->insert('CBA'); $queue->extract(); $queue->insert('ABW'); $queue->insert('NKOTB'); $queue->extract(); $queue->insert('1Pierwszy'); $queue->extract(); $queue->insert('2Drugi'); $queue->insert('3Ostatni'); $queue->extract(); $queue->insert('abc'); $queue->insert('abCadabra'); echo '---pozostałe---<br>'; while($queue->valid()) { $queue->extract(); } ?>
Widać powyżej, że przeplatamy dodawanie i wyciąganie elementów. Na koniec sprawdzamy czy coś jest w kolejce i wyciągamy.
Co zwróci nam powyższe wywołanie kodu? Domyślnie kolejka nie ignoruje małych i dużych liter oraz stawia liczby jako ważniejsze od liter. Otrzymamy:
Dodaję: ABC
Dodaję: CBA
Wyciągam: ABC
Dodaję: ABW
Dodaję: NKOTB
Wyciągam: ABW
Dodaję: 1Pierwszy
Wyciągam: 1Pierwszy
Dodaję: 2Drugi
Dodaję: 3Ostatni
Wyciągam: 2Drugi
Dodaję: abc
Dodaję: abCadabra
---pozostałe---
Wyciągam: 3Ostatni
Wyciągam: abCadabra
Wyciągam: abc
Wyciągam: CBA
Wyciągam: NKOTB
Jeżeli zignorujemy wielkość liter, a liczby ustawimy jako mniej ważne od liter to otrzymamy:
Dodaję: ABC
Dodaję: CBA
Wyciągam: ABC
Dodaję: ABW
Dodaję: NKOTB
Wyciągam: ABW
Dodaję: 1Pierwszy
Wyciągam: CBA
Dodaję: 2Drugi
Dodaję: 3Ostatni
Wyciągam: NKOTB
Dodaję: abc
Dodaję: abCadabra
---pozostałe---
Wyciągam: abc
Wyciągam: abCadabra
Wyciągam: 1Pierwszy
Wyciągam: 2Drugi
Wyciągam: 3Ostatni
Fajne, co?
Mechanizm sortowania zrobiłem od zera sam. Dostępny jest tutaj. Możecie sobie robić z nim co chcecie (pod warunkiem napisania pozytywnego komentarza pod wpisem i ewentualnym kliknięciem na „Lubię to” :-) ). Komentowałem po angielsku (trochę zwiększę tym audytorium, a Wam zapewne nie zrobi różnicy).
Podobne wpisy:

O autorze