You are on page 1of 16

Algorytmy i Struktury Danych

(wykªad 003 - Sorting)

Edward Szczypka

04 listopada 2022

1 / 16
Najlepsze Algorytmy Sortowania przez Porównanie
Najlepszy pesymistyczny czas mo»liwy do uzyskania przy sortowaniu
przez prównanie to O(n log2 n), wykorzystuj¡cy co najmniej
n log2 n + O(n) porówna«.

Algorytm sortowania mo»na


przedstawi¢ w postaci drzewka
decyzyjnego.
optymistyczna
▶ w¦zªy wewn¦trzne - porównanie
elementów pesymistyczna
▶ li±cie - uporz¡dkowana
permutacja

Dªugo±¢ ±ciezki do odpowiedniego


w¦zªa, to czas dziaªania
algorytmu.
Najdªu»sza ±cie»ka od korzenia to zªo»ono±¢ pesymistyczna, najkrótsza
optymistyczna.
Najlepsze algorytmy maj¡ wyrównane dªugo±ci ±cie»ek (najlepiej ró»nica
poziomów conajwy»ej 1). Wtedy najlepsza zªo»ono±¢ pesymistyczna, to
log2 n! + O(n) = n log2 n + O(n).
2 / 16
Najlepsze Algorytmy Sortowania przez Porównanie

Najlepszy ±redni czas sortowania algorytmu przez porównanie mo»na


oszacowac od doªu metoda kompresji.

Ponownie przedstawiamy algorytm


sortowania w postaci drzewka
decyzyjnego. krótkie kody

▶ w¦zªy wewn¦trzne - porównanie


elementów
▶ li±cie - uporz¡dkowana
permutacja dªugie kody

Dªugo±¢ ±ciezki do odpowiedniego


w¦zªa, to czas dziaªania
algorytmu.
Permutacje jak w Heapsorcie kodujemy za pomoc¡ ±cie»ki do
odpowiedniej permujacji,
Im dªu»sza ±cie»ka tym dªu»ej dziaªaª algorytm sortowania.
Za pomoc¡ metody kompresji mo»na pokaza¢, »e zªo»ono±¢ ±rednia
wynosi co najmneij log2 n! − O(n) = n log2 n − O(n).
3 / 16
Najlepsze Sortowanie Trzech Elementów
Poni»ej najlepszy algorytm sortowania trzech elementów w postaci drzewka.
a[0] ≶ a[1]
< >
a[1] ≶ a[2] a[0] ≶ a[2]
< > < >
a[0] < a[1] < a[2] a[0] ≶ a[2] a[1] < a[0] < a[2] a[1] ≶ a[2]
< > < >
a[0] < a[2] < a[1] a[2] < a[0] < a[1] a[1] < a[2] < a[0] a[2] < a[1] < a[0]

Zªo»ono±¢ pesymistyczna ilo±ci porówna«:


W (3) = 3,
Zªo»ono±¢ optymistyczna ilo±ci porówna«:
Opt(3) = 2,
Zªo»ono±¢ ±rednia ilo±ci porówna«:
A(3) = 2 × 2 × 1
6 +4×3× 1
6 = 8
3 = 2.6666(6),
Wra»liwo±¢ pesymistyczna (nie da si¦ jej zmniejszy¢):
∆(3) = 1,
Wra»liwo±¢
q ±rednia:2 2
δ(3) = 2 2 − 83 16 + 4 3 − 83 16 ≈ 0.47140.

4 / 16
Sortowanie sªabo wykorzystuj¡ce porównania

Maj¡c informacj¦ o budowie sortowanych elementów


▶ maksymalna dªugo±¢ napisów,
▶ dªugo±¢ reprezentacji bitowej liczb,
▶ zakres liczb,
mo»na dostosowa¢ reguªy sortowania.
Przykªady sortowa«:
▶ Pozycyjne (Radix Sort),
▶ Przez zliczanie,
▶ Kubeªkowe (wariant przez zliczanie),
▶ Interploacyjne (wariant kubeªkowego).

5 / 16
RadixSort

01010001 11001000 11110000 00000001 00000001


00000001 00101000 01010001 11001000 00001111
11001000 11110000 00000001 00001111 00101000
00101000 01010001 01010101 01010001 01010001
00001111 00000001 11001000 01010101 01010101
11110000 01010101 00101000 00101000 10101010
10101010 10101010 10101010 10101010 11001000
01010101 00001111 00001111 11110000 11110000

Rysunek: Sortowanie 8-bitowych liczb w 4 fazach sortowa« liczb 2 bitowych

protected static int d = 8;


protected static int w = 32;
public static int[] radixSort(int[] a) {
int[] b = null;
for (int p = 0; p < w/d; p++) {
int c[] = new int[1<<d];
// the next three for loops implement counting-sort
b = new int[a.length];
for (int i = 0; i < a.length; i++)
c[(a[i] >> d*p)&((1<<d)-1)]++;
for (int i = 1; i < 1<<d; i++)
c[i] += c[i-1];
for (int i = a.length-1; i >= 0; i--)
b[--c[(a[i] >> d*p)&((1<<d)-1)]] = a[i];
a = b;
}
return b;
}
6 / 16
RaidxSort

W tym kodzie c[(a[i] >> d ∗ p)&((1 << d) − 1)] + + wyci¡ga liczb¦


caªkowite, które s¡ reprzezentowane przez bity (p + 1)d − 1, . . . , pd liczby
a[i].
Dalszy fragment kodu to tak naprawd¦ u»yty algorytm sortowania przez
zliczanie.
Ka»da faza wymaga θ(n + 2d ) kroków.
Faz mamy w/d, gdzie w-to ilo±¢ bitów w liczbie.
Twierdzenie
Dla dowolnego naturaknego d > 0, procedura RadixSort(a, k) sortuje tablic¦ a
w

z liczbami w-bitowymi w czasieΘ d (n + 2d ) .

7 / 16
Sortowanie przez zliczanie

a 7 2 9 0 1 2 0 9 7 4 4 6 9 1 0 9 3 2 5 9

c 3 2 3 1 2 1 1 2 0 5
0 1 2 3 4 5 6 7 8 9
c0 3 5 8 9 11 12 13 15 15 20

b 0 0 0 1 1 2 2 2 3 4 4 5 6 7 7 9 9 9 9 9
0 1 2 3 4 5 6 8
7 9
c0 3 5 8 9 11 12 13 15 20

a 7 2 9 0 1 2 0 9 7 4 4 6 9 1 0 9 3 2 5 9
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

Rysunek: Sortowanie 8-bitowych liczb w 4 fazach sortowa« liczb 2 bitowych

public static int[] countingSort(int[] a, int k) {


int c[] = new int[k];
for (int i = 0; i < a.length; i++)
c[a[i]]++;
for (int i = 1; i < k; i++)
c[i] += c[i-1];
int b[] = new int[a.length];
for (int i = a.length-1; i >= 0; i--)
b[--c[a[i]]] = a[i];
return b;
}

8 / 16
Sortowanie Przez Zliczanie

Dla ka»dego i ∈ {0, . . . , k − 1} zliczamy ilo±¢ wystapie« i za pomoc¡ c[i],


▶ c[0] reprezentuje ilo±¢ wyst¡pie« 0,
▶ . . . . . . . . .,
▶ c[k − 1] reprezentuje ilo±¢ wyst¡pie« k − 1,
co zajmuje Θ(n) kroków,
W nast¦pnym kroku, który zajmuj O(k) kroków, zliczamy
c[i] = c[i] + c[i − 1],
▶ W c[i] mamy ilo±¢ elementów mniejszych, lub równych c[i],
W Θ(n) krokach element z pozycji i czyli a[i] = j ,
▶ wkªadamy do tablicy wynikowej b na pozycj¦ c[j] − 1, czyli b[c[j] − 1] = j ,
▶ zmniejszamy licznik c[j], czyli c[j] − −,

Twierdzenie
Sortowanie przez zliczanie elementów ze zbioru {0, . . . , k − 1} wykonywane jest
w czasie Θ(n + k).

9 / 16
Sortowanie Kubeªkowe

Nie da si¦ zastosowa¢ sortowania przez zliczanie


▶ dla liczb rzeczywistych,
▶ dla bardzo du»ego zakresu liczb caªkowitych k >> n,
▶ ......
modykacja sortowania przez zliczanie - sortowanie kubeªkowe,
modykacja sortowania kubeªkowego - sortowanie interpolacyjne.

10 / 16
Sortowanie Interpolacyjne
// Uwaga to jest pseudo kod w C++
int minIdx=0;
int maxIdx=10000;

double data[];

// stare dobre twierdzenie Talesa


int phi(int x, int numBuckets, double minVal, double maxVal){
return ( x-minVal )*( maxBucketIdx-0 )/( maxVal-minVal );
}

double [] InterpolationSort( double data[], int minIdx, int maxIdx, ){

double minVal=GetMin( data, minIdx, maxIdx );


double maxVal=GetMax( data, minIdx, maxIdx );

double outData[];
int numBuckets=100;
int buckets[maxBuckets];

// Zliczamy ilo±¢ elementów w kubeªkach


for( int i=minIdx; i<maxIdx; i++ )
buckets[ phi( data[i], numBuckets, minVal, maxVal ) ]++;

// Kubeªek o numerze j, znajduje si¦ na miejscu od buckets[j-1] do buckets[j]-1


for( int j=1; j<numBuckets; j++ )
buckets[j] += buckets[j-1];

// przekªadamy elementy z wej±cia na odpowiednie miejsce tablicy wyj±ciowej


// zmniejszaj¡c od razu ilo±¢ elementów odpowiedniego kubeªka
for( int i=minIdx; i<maxIdx; i++ )
outData[ --buckets[ phi( data[i], numBuckets, minVal, maxVal ) ]]=data[i];

// doka«czamy sortowanie za pomoc¡ sortowania przez wstawianie


// zwykªy quicksort w tym przypadku b¦dzie zªy!!!!
return InsertionSort( outData, minIdx, maxIdx );
}

11 / 16
Sortowanie Interpolacyjne
Na wyszukiwanie minimalnej, maksymalnej warto±ci w tablicy oraz trzy
pierwsze p¦tle potrzeba co najwy»ej cn czasu dla pewnego c.
Je±li rozkªad danych jest jednostajny, to kubeªki s¡ podobnej wielko±ci
n/m, gdzie m oznacza ilo±¢ kubeªków.
Wykorzystane sortowanie przez wstawianie:
▶ Operacje porównania i przesuwania ogranicza jedynie do aktualnie
rozpatrywanego kubeªka.
▶ Wykorzystuje wartownika aby nie przej±¢ do poprzedniego kubeªka.
▶ Poniewa» przy równomiernym rozkªadzie danych kubeªki maja podobny
rozmiar, to przybli»ony czas dziaªania tej cz¦±ci wynosi:

n
 
m ∗ Tw
m
gdzie Tw (n/m) oznacza czas sortowania przez wstawianie dla n/m danych.
▶ Poniewa» sortowanie przez wstawianie wykorzystuje pesymisytcznie
1 2
2
n + O(n) porówna«, to cz¦±¢ z tym sortowaniem wykona:
  2 
1 n n 1 2

m∗ +O = n + O(n)
2 m m 2m
porówna«.
12 / 16
Sortowanie Interpolacyjne

Aby u»y¢ quicsorta, trzeba wybra¢ sensownie pivot.


Sortowanie interpolacyjne mo»na wywoªywa¢ rekurencyjnie dla wcze±niej
wydzielonych kubeªków. Je±li rozkªad danych jest równomierny, to przy
funkcji phi zbudowanej w oparciu o twierdzenie Talesa, przybli»ony czas
dziaªania takiego algorytmu, okre±la równanie rekurencyjne:
Ta (1) = 0
Ta (n) ≈ m ∗ Ta (n/m) + c ∗ n

dla pewnego c.
Odpowiednia budowa funkcji phi, przy innym rozkªadzie danych rownie»
mo»e zapewni¢ przybli»on¡ wielko±¢ wszystkich kubeªków.
Z twierdzenia o rekurencji uniwersalnej mo»na wyliczy¢ T (n).
Uwaga: Prosz¦ samodzielnie wykona¢ odpowiednie obliczenia.

13 / 16
Twierdzenie o rekurencji uniwersalnej
Je±li funkcja T (n) dla a ­ 1, b > 1, n > 0 zdeniowanej jako
(
Θ(1) dla 1 ¬ n ¬ b,
T (n) =
aT ( nb ) + f (n) dla n ­ b

oraz funkcja f jest dodatnia to:


je±li f (n) = O nlogb a−ϵ dla pewnej staªej ϵ > 0, to T (n) = Θ nlogb a ,
 

je±li f (n) = Θ nlogb a , to T (n) = Θ nlogb a log n ,


 

je±li f(n) = Ω nlogb a+ϵ dla pewnej staªej ϵ > 0, a dodatkowo




af nb ¬ cf (n) to T (n) = Θ (f (n)),

Uwaga: Prosz¦ równie» udowodni¢ twierdzenie o rekursji uniwersalnej.

14 / 16
Sortowanie Interpolacyjne
Dokªadniejsza analiza ±redniego czasu sortowania interploacyjnego.
m kubeªków,
element x do dowolnego pudeªka traa z równym prawdopodobie«stwem,
czyli p = m1 ,
w danym pudeªku, b¦dziemy mieli ±rednio
Pn
i ni pi (1 − p)n−i

i=0
elementów. U»ywaj¡c to»samo±ci: ni = ni n−1i−1 .
 

n   n  
X n i X n i
i p (1 − p)n−i = i p (1 − p)n−i
i=0
i i=1
i
n   n  
X n−1 i n−i
X n−1 i n−i
= n p (1 − p) = n p (1 − p)
i=1
i − 1 i=1
i − 1
n−1
X n−1 
(n−1)−i
= np pi (1 − p) = np(p + 1 − p)n−1 = np
i=0
i

je±li zatem n = O(m) to np = O(1), ±rednia ilo±¢ elementów w takim


kubeªku jest staªa.
15 / 16
Sortowanie Interpolacyjne

sortowanie przez wstawianie ma ±redni czas θ(k2 ) dla k elementów,


 
n 2
u nas b¦dzie to czas ±rednio θ((np)2 ) = θ ,

m
mamy m kubeªków, wi¦c ±redni czas sortowania wynosi
n2 n2
   
mθ =θ
m2 m

dla n = O(m) dostajemy czas liniowy O(n).


Rozumowanie mo»na rozszerzy¢ na rekurencyjne wywoªania (metoda dziel
i zwyci¦»aj) przy du»o mniejszej ilo±ci kubeªków ni» ilo±¢ elementów.

16 / 16

You might also like