Sortowanie w czasie liniowym

Sortowanie w czasie liniowym 1 Sortowanie - zadanie Definicja (dla liczb): wejście: ciąg n liczb A = (a1, a2, …, an) wyjście: permutacja (a1,…, a’n...
131 downloads 0 Views 202KB Size
Sortowanie w czasie liniowym

1

Sortowanie - zadanie Definicja (dla liczb): wejście: ciąg n liczb A = (a1, a2, …, an) wyjście: permutacja (a1,…, a’n) taka, że a’1 ≤ … ≤ a’n Po co sortować? –  Podstawowy problem dla algorytmiki –  Wiele algorytmów wykorzystuje sortowanie jako procedurę pomocniczą –  Pozwala pokazać wiele technik –  Dobrze zbadane (czas)

2

Zestawienie czasów działania Ø  Przez wybór: O(N2) zawsze Ø  Bąbelkowe: O(N2) najgorszy przypadek; O(N) najlepszy przyp. Ø  Wstawianie: O(N2) średnio; O(N) najlepszy przypadek Ø  Shellsort:

O(N3/2)

Ø  Heapsort:

O(NlogN) zawsze

Ø  Mergesort:

O(NlogN) zawsze

Ø  Quicksort:

O(NlogN) średnio; O(N2) najgorszy przypadek

Ø  Zliczanie:

O(N) zawsze

Ø  Radix sort:

O(N) zawsze

Ø  zewnętrzne: O(b logb)) dla pliku o b „stronach”.

3

Przegląd

Ø  Czy możliwe jest sortowanie w czasie lepszym niż dla metod porównujących elementy (poprzednio – najlepsze algorytmy dawały czas O(NlogN))? Ø  Algorytmy o liniowym czasie działania: –  Przez zliczanie (Counting-Sort) –  Pozycyjne (Radix-Sort) –  Kubełkowe (Bucket-sort) Ø  Potrzeba dodatkowych założeń!

4

Sortowanie o czasie liniowym

Ø  Możliwe przy dodatkowych informacjach (założeniach) o danych wejściowych. Ø  Przykłady takich założeń: –  Dane są liczbami całkowitymi z przedziału [0..k] i k = O(n). –  Dane są liczbami wymiernymi z przedziału [0,1) o rozkładzie jednostajnym na tym przedziale Ø  Trzy algorytmy: –  Counting-Sort –  Radix-Sort –  Bucket-Sort

5

Zliczanie (Counting sort) wejście: n liczb całkowitych z przedziału [0..k], dla k = O(n). pomysł: dla każdego elementu wejścia x określamy jego pozycje (rank): ilość elementów mniejszych od x. jeśli znamy pozycję elementu – umieszczamy go na r+1 miejscu ciągu przykład: jeśli wiemy, że w ciągu jest 6 elementów mniejszych od 17, to 17 znajdzie się na 7 miejscu w ciągu wynikowym. powtórzenia: jeśli mamy kilka równych elementów umieszczamy je kolejno poczynając od indeksu pozycja

6

Zliczanie (Counting sort)

A= 4 2 1 3 5

Dla każdego A[i], liczymy elementy ≤ od niego. Daje to rank (pozycję) elementu

Rank = 1 2 3 4 5

B=

1 2 3

4 5

Jeśli nie ma powtórzeń i n = k, Rank[A[i]] = A[i] i B[Rank[A[i]] ß A[i]

7

Zliczanie (Counting sort)

A= 5 2 1 3 Rank = 1 2 3

B=

1 2 3

Jeśli nie ma powtórzeń i n < k,

4

5

Niektóre komórki tablicy rank pozostają niewykorzystane, ale algorytm działa.

8

Zliczanie (Counting sort)

A= 4 2 1 2 3

Jeśli n > k i mamy powtórzenia,

Rank = 1 32 4 5

B= 1 2 2

3 4

umieszczamy na wyjściu powtarzające się elementy w takiej kolejności, w jakiej występowały w oryginalnym ciągu (stabilność)

9

Zliczanie (Counting sort) A[1..n] – tablica wejściowa B [1..n] – tablica wyjściowa C [0..k] – pomocnicza tablica (do zliczania) Counting-Sort(A, B, k) 1.  for i ß 0 to k 2.  do C[i] ß 0 3.  for j ß 1 to length[A] 4.  do C[A[j]] ß C[A[j]] +1 5.  /* C zawiera ilości elementów równych i 6.  for i ß 1 to k 7.  do C[i] ß C[i] + C[i –1] 8.  /* C zawiera ilości elementów ≤ i 9.  for j ß length[A] downto 1 10.  do B[C[A[j]]] ß A[j] 11.  C[A[j]] ß C[A[j]] – 1

10

Sortowanie przez zliczanie – przykład (1) 1

2

3

4

5

6

7

8

A= 2 5 3 0 2 3 0 3 0

1

2

3

4

5

C[A[j]] ß C[A[j]] +1 po p.4

C= 2 0 2 3 0 1 0

1

2

3

4

5 C[i] ß C[i] + C[i –1] po p. 7

C= 2 2 4 7 7 8 1

2

3

4

5

n=8 k=6

6

7

8

3

B= 0

1

2

C= 2 2 4

3

4

76 7 8

5

B[C[A[j]]] ß A[j] C[A[j]] ß C[A[j]] – 1 po p. 11 11

Sortowanie przez zliczanie – przykład (2) 1

2

3

4

5

6

7

8

A= 2 5 3 0 2 3 0 3 0

1

2

3

4

5

C= 2 2 4 6 7 8 1

2

3

4

5

6

7

3

0

B= 0

1

8

2

3

4

5

C = 21 2 4 6 7 8 12

Sortowanie przez zliczanie – przykład (3) 1

2

3

4

5

6

7

8

A= 2 5 3 0 2 3 0 3 0

1

2

3

4

5

C= 2 2 4 6 7 8 1

2

3

4

5

0

1

7

8

3 3

0

B=

6

2

3

4

5

C = 1 2 4 65 7 8 13

Counting sort – czas działania Ø  Pętla for w p.1-2 zajmuje czas Θ(k) Ø  Pętla for w p.3-4 zajmuje czas Θ(n) Ø  Pętla for w p.6-7 zajmuje czas Θ(k) Ø  Pętla for w p.9-11 zajmuje czas Θ(n) Ø  Stąd dostajemy łączny czas Θ(n+k) Ø  Ponieważ k = O(n), T(n) = Θ(n)

à algorytm jest optymalny!!

Ø  Konieczne jest założenie k = O(n). Jeśli k >> n to potrzeba to potrzeba dużej ilości pamięci. Ø  Nie jest to sortowanie „w miejscu”.

14

Radix sort – sortowanie pozycyjne wejście: n liczb całkowitych, d-cyfrowych, łańcuchów o d-pozycjach pomysł: zajmować się tylko jedną z cyfr (sortować względem kolejnych pozycji – cyfr/znaków). Zaczynamy od najmniej znaczącej cyfry/ znaku, potem kolejne pozycje (cyfry/znaki), aż do najbardziej znaczącej. Musimy stosować metodą stabilną. Ponieważ zbiór możliwych wartości jest mały (cyfry – 0-9, znaki ‘a’-’z’) możemy zastosować metodę zliczania, o czasie O(n)

Po zakończeniu ciąg będzie posortowany!!

15

Radix sort – przykład

329

720

720

329

457

355

329

355

657

436

436

436

839

457

839

457

436

657

355

657

720

329

457

720

355

839

657

839

16

Radix-Sort – pseudokod

Radix-Sort(A, d) 1.  2. 

for i ß 1 to d do zastosuj stabilną metodę sortowania do cyfry d dla tablicy A

uwagi: •  złożoność: T(n) = Θ(d(n+k)) à Θ(n) dla stałego d i k = O(1) •  wartości cyfr/znaków są z zakresu [0..k –1] dla k = O(1) •  Metoda stosowana dla poszczególnych pozycji musi być stabilna!

17

Sortowanie kubełkowe – Bucket sort wejście: n liczb rzeczywistych z przedziału [0..1) ważne jest, aby były równomiernie rozłożone (każda wartość równie prawdopodobna) pomysł: dzielimy przedział [0..1) na n podprzedziałów („kubełków”):0, 1/n, 2/n. … (n–1)/n. Elementy do odpowiednich kubełków, ai: 1/i ≤ ai ≤ 1/(i+1). Ponieważ rozkład jest równomierny to w żadnym z przedziałów nie powinno znaleźć się zbyt wiele wartości. Jeśli wkładamy je do kubełków zachowując porządek (np. przez wstawianie – Insertion-Sort), dostaniemy posortowany ciąg.

18

Bucket sort – przykład .78 .17 .39 .26 .72 .94 . 21

0

.12

1

.12

2

.21

3

.39

.23

.26

.21 .23

4

.26

5

.39

6

.68

.23

7

.72

.68

8

.12

.17

.17

9

.68 .78

.72 .78

.94

.94 19

Bucket-Sort A[i] tablica wejściowa B[0], B[1], … B[n –1] lista „kubełków”

Bucket-Sort(A) 1.  n ß length(A) 2.  for i ß 0 to n 3.  do wstaw A[i] do listy B[floor(nA[i])] 4.  for i ß 0 to n –1 5.  do Insertion-Sort(B[i]) 6.  Połącz listy B[0], B[1], … B[n –1]

20

Bucket-Sort – złożoność czasowa Ø  Wszystkie instrukcje z wyjątkiem 5 (Insertion-Sort) wymagają czasu O(n), w przypadku pesymistycznym. Ø  W przypadku pesymistycznym, O(n) liczb trafi do jednego „kubełka” czyli ich sortowanie zajmie czas O(n2). Ø  Jednak w średnim przypadku stała ilość elementów wpada do jednego przedziału – stąd czas średni wyniesie O(n).

21

Suggest Documents