Prezentowane materiały są przeznaczone dla uczniów szkół ponadgimnazjalnych Autor artykułu: mgr Jerzy Wałaszek |
©2014 mgr
Jerzy Wałaszek
|
Proste rozwiązanie tego problemu jest następujące:
Przygotowujemy pusty zbiór M, w którym będziemy składowali k
największych elementów. Przeglądamy zbiór T i kolejne
elementy próbujemy wstawić do M. Element zbioru T
trafia do M wtedy, gdy zbiór M nie jest
jeszcze zapełniony lub gdy element zbioru T jest większy od
pierwszego elementu zbioru M. Elementy wstawiamy, tak aby zbiór
M był uporządkowany nierosnąco. Gdy zakończymy przeglądanie
zbioru T w pierwszym elemencie zbioru
M będzie k-ty największy element zbioru T.
Wyjaśnienia wymaga sposób działania na zbiorze M. Odwzorujemy go w tablicy (k + 1) elementowej. Do wstawiania elementów wykorzystamy ideę wartowników, którą opisaliśmy w rozdziale o wyszukiwaniu liniowym z wartownikiem. Tablicę M wypełnimy od M[0] do M[k-1] najmniejszą liczbą całkowitą – zagwarantuje to wstawianie najmniejszych elementu zbioru Z, jeśli w M jest jeszcze miejsce. Na ostatniej pozycji M[k] umieścimy największą liczbę całkowitą – zagwarantuje nam ona, iż wstawiane elementy nie wyjdą poza k-1 pozycję.
Algorytm wyszukiwania k-tego największego elementu – wersja nr 1Wejście
Wyjście:k-ta największa wartość elementu w tablicy T. Dodatkowo M[0]...M[k-1] tworzy ciąg wartości maksymalnych z tablicy T. Elementy pomocnicze:
Lista kroków:
Jeśli zbiór T jest bardzo duży lecz wartości jego elementów tworzą względnie mały przedział liczb całkowitych, to do wyznaczenia k-tego największego elementu można wykorzystać następujące rozwiązanie:
Tworzymy tablicę L posiadającą tyle elementów, ile liczb
całkowitych zawiera przedział <minT,maxT>
(wartość minimalna i maksymalna elementów zbioru T).
Elementy L zerujemy – będą one pełniły rolę liczników
elementów zbioru T. Teraz przeglądamy zbiór T od
pierwszego do ostatniego elementu i odpowiednio zliczamy napotkane
elementy T w licznikach L. Na koniec przeglądamy
liczniki L od ostatniego (odpowiada
maxT)
do pierwszego (odpowiada minT).
Ponieważ licznik L[i] zawiera informację o tym, ile razy
wartość i występuje w T, to przy każdym kolejnym
liczniku odejmujemy jego stan od k. Jeśli k wyzeruje
się lub przyjmie wartość ujemną, to poszukiwana wartość jest równa
indeksowi licznika, który spowodował tę sytuację.
Klasa złożoności obliczeniowej tak zdefiniowanego algorytmu wynosi O(n + m), gdzie n oznacza liczbę elementów w zbiorze T, a m liczbę ich możliwych wartości. Dodatkowo algorytm wymaga O(m) komórek pamięci na przechowanie liczników. Musimy również znać zakres wartości elementów zbioru T – można tutaj wykorzystać algorytm jednoczesnego wyszukiwania min i max.
Algorytm wyszukiwania k-tego największego elementu – wersja nr 2Wejście
Wyjście:k-ta największa wartość elementu w tablicy T. Elementy pomocnicze:
Lista kroków:
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Przykładowe dane do ćwiczeń
Pierwsza liczba to n – ilość elementów w tablicy T.
Druga liczba to k – numer największej wartości. Następne
n liczb to zawartość tablicy T.
80 10 |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Szybkie wyszukiwanie k-tego największego elementuJeśli nie musimy zachowywać oryginalnej kolejności elementów w zbiorze T, to istnieje szybki algorytm znajdowania k-tego największego elementu, który posiada oczekiwaną klasę złożoności obliczeniowej równą O(n log n) (liniowo logarytmiczna). Algorytm ten nosi nazwę Szybkiego Wyszukiwania (ang. Quick Select) i został opracowany przez profesora Tony'ego Hoare'a, twórcę jednego z najszybszych algorytmów sortujących – Sortowania Szybkiego (ang. Quick Sort). Działanie algorytmu Szybkiego Wyszukiwania oparte jest na zasadzie Dziel i Zwyciężaj (ang. Divide and Conquer). Polega ona na rekurencyjnym podziale pierwotnego problemu na problemy prostsze tego samego typu. Podział wykonywany jest dotąd, aż rozwiązanie stanie się oczywiste. Następnie z rozwiązań podproblemów tworzymy rozwiązania na wyższych poziomach aż dojdziemy do rozwiązania problemu pierwotnego W przypadku Szybkiego Wyszukiwania postępujemy w sposób następujący:
W zbiorze T wybieramy dowolny element. Oznaczmy go przez v i nazwijmy elementem zwrotnym (ang. pivot). Następnie dokonujemy podziału zbioru T na dwa podzbiory TL i TP (lewy i prawy). W podzbiorze TP powinny znaleźć się elementy o wartościach nie większych od v. Z kolei w podzbiorze TP powinny być elementy o wartościach nie mniejszych od v. Sam element v musi być pierwszym elementem podzbioru TP. Po takim podziale sprawdzamy, czy v jest (n - k)-tym elementem zbioru T. Jeśli tak, to v jest k-tym największym elementem w tym zbiorze. Jeśli nie, to za nowy zbiór do podziału przyjmujemy ten z podzbiorów TL lub TP, w którym występuje pozycja (n - k)-ta i całą procedurę powtarzamy aż do znalezienia k-tego największego elementu.
Podział zbioru na dwie partycjePodstawowym problemem w algorytmie Szybkiego Wyszukiwania
jest podział zbioru na dwa podzbiory, partycje, o wymaganych własnościach.
Ponieważ zbiór T będziemy odwzorowywali w tablicy
ip – przechowuje indeks pierwszego
elementu podzbioru – początek
Początkowo podzbiór obejmuje cały zbiór T, zatem zmienne te przyjmują odpowiednio wartości:
ip = 0
Element zwrotny można wybierać na różne sposoby.
Poniżej podajemy algorytm partycjonowania zbioru wg pierwszego elementu partycji głównej. Jeśli zechcemy partycjonować wg innego elementu zwrotnego, to po prostu wymieniamy wybrany element zwrotny z pierwszym elementem partycji i dalej wykorzystujemy podany poniżej algorytm.
Algorytm partycjonowania zbioru wg pierwszego elementuFunkcja Dziel_na_partycje(T,ip,ik)Wejście
Wyjście:j – pozycja elementu zwrotnego w T. Element ten dzieli partycję wejściową na dwie partycje:
Elementy pomocnicze:
Lista kroków funkcji Dziel_na_partycje(T,ip,ik):
Algorytm szybkiego wyszukiwania k-tego największego elementu - wersja nr 3Wejście
Wyjście:Wartość k-tego największego elementu zbioru T. Elementy pomocnicze:
Dziel_na_partycje(T,ip,ik) – funkcja dzieląca na dwie partycje wg elementu zwrotnego. Funkcja opisana powyżej. Lista kroków:
|
I Liceum Ogólnokształcące |
Pytania proszę przesyłać na adres email: i-lo@eduinf.waw.pl
W artykułach serwisu są używane cookies. Jeśli nie chcesz ich otrzymywać,
zablokuj je w swojej przeglądarce.
Informacje dodatkowe