aisd - 3 sortowanie i statystyki pozycyjne (1).pdf
TRANSCRIPT
-
Algorytmy i struktury
danych sortowanie - pojcia wstpne,
podstawowe alg. sortowania tablic,
zaawansowane alg. sortowania tablic,
kolejki priorytetowe oparte o kopiec
sortowanie w czasie liniowym,
statystyki pozycyjne
-
Sortowanie
Uporzdkowanie elementw
Klucz fragment danych, dla ktrego jest okrelona
relacja uporzdkowania
Zoono problemu najlepszy znany algorytm
Sortowanie tablic czy plikw
Zachowanie uporzadkowania czciowego
Mediana
Statystyka pozycyjna
-
Indeksy
Bezporednie sortowanie elementw
Sortowanie indeksu
1 7 2 4 8 11 9 5
1 7 2 4 8 11 7 2
bezporednie
0 2 3 7 1 4 6 5
index
-
Klasyczne algorytmy dla tablic
sortowanie przez wstawianie (Insertion Sort)
w kolejnym kroku nastpny element z czci nie posortowanej
wstawiany jest na odpowiedni pozycj czci posortowanej
sortowanie przez wybieranie (Selection Sort)
w kolejnym kroku najwikszy (najmniejszy) element z czci
nie posortowanej wstawiany jest na koniec czci posortowanej
sortowanie przez zamian (Exchange, Bubble Sort)
zamiana elementw miejscami a do skutku
N. Wirth Algorytmy+Struktury danych = programy
-
Sortowanie bbelkowe
1 7 2 4 8 11 7 2
2 7
I II 4
7
7 11 2 11
III IV
for j in range(0,n):
for i in range(0,n-1):
if(A[i] > A[i+1]):
A[i],A[i+1] = A[i+1],A[i]
-
Sortowanie bbelkowe
1 7 2 4 8 11 7 2
2 7 4 7
7 11 2 11
I II
1 7 2 4 8 11 7 2
2 7 4 7
7 11 2 11
7 8 2 8
for j in range(0,n):
for i in range(0,n-1):
if(A[i] > A[i+1]):
A[i],A[i+1] = A[i+1],A[i]
-
Sortowanie bbelkowe
//wariant podstawowy for j in range(0,n):
for i in range(0,n-1):
if(A[i] > A[i+1]):
A[i],A[i+1] = A[i+1],A[i]
//wariant ulepszony wewntrzna ptla nie przeglda
//uporzdkowanych elementw for j in range(n-1,-1,-1):
for i in range(0,j):
if(A[i] > A[i+1]):
A[i],A[i+1] = A[i+1],A[i]
-
Sortowanie bbelkowe
//wariant ulepszony - detekcja koniecznoci powtrze for j in range(n-1,-1,-1):
change = false
for i in range(0,j):
if(A[i] > A[i+1]):
A[i],A[i+1] = A[i+1],A[i]
change = true
if not change: break
-
Sortowanie bbelkowe
Waciwoci:
alg. prosty w implementacji
zoono O(n2)
zwizy kod - mae stae proporcjonalnoci
zachowuje uporzdkowania czciowe
Stosunkowo najgorsze zachowanie spord prostych
metod
-
Sortowanie przez proste
wstawianie
zachowuje uporzdkowania czciowe
pesymistyczna zoono O(N2)
mniej zapisw ni przy sortowaniu przez zamian parami
1 7 2 8 11 4 7 2
2 7
X = 1 X = 7 X = 2 for i in range (1, n)
x = A[i]
p = znajdz_miejsce_na(x)
A[p] = x
-
Sortowanie przez proste
wstawianie
1 2 7 8 11 4 7 2
4 7 8
11
X = 2 X = 8 X = 11 X = 4
zachowuje uporzdkowania czciowe
pesymistyczna zoono O(N2)
mniej zapisw ni przy sortowaniu przez zamian parami
for i in range (1, n)
x = A[i]
p = znajdz_miejsce_na(x)
A[p] = x
-
Sortowanie przez proste
wstawianie
def ProsteWstawianie(A, n):
for i in range (1, n):
x = A[i]
for j in range (i-1, -1, -1):
if x>=A[j] : break
A[j+1] = A[j]
A[j+1] = x
-
Sortowanie Shella Zaawansowane sortownie przez wstawianie elementw
1. Wybieramy k = kp
2. Sortujemy przez wstawianie proste podciagi caej tablicy (co
k-ty element)
3. zmniejszamy k tak dugo a osignie 1
o zoonoci alg. decyduje kp i sposb zmiany k
kp = 1 oznacza zwyke sortowanie
dla ki = 2i - 1 (....., 31, 15, 7, 3, 1 )
algorytm ma zoono O(N1.2)
dla ki = 2r3q (r,q N) (......, 20, 16, 10, 9, 8, 6, 4, 3, 2, 1)
algorytm ma zoono O(N log2N)
algorytm zachowuje uporzdkowanie czciowe
-
Sortowanie Shella
1 2 7 8 11 4 7 2
4
zachowuje uporzdkowanie czciowe
pesymistyczna zoono O(N1.2)
for k in [ ..., 31, 15, 7, 3, 1] :
sortuj_przez_wstawianie_k_podtablic(A)
#A[0],A[k],A[2k] ...
#A[1],A[k+1],A[2k+1] ...
#...
#A[k-1],A[2k-1],A[3k-1] ...
k=7
-
Sortowanie Shella
1 2 7 8 11 4 7 2
4
zachowuje uporzdkowanie czciowe
pesymistyczna zoono O(N1.2)
for k in [ ..., 31, 15, 7, 3, 1] :
sortuj_przez_wstawianie_k_podtablic(A)
#A[0],A[k],A[2k] ...
#A[1],A[k+1],A[2k+1] ...
#...
#A[k-1],A[2k-1],A[3k-1] ... 1 2 4 8 11 4 7 2 11
2
k=7 k=3
8
7
-
Sortowanie Shella def ShellSort (A, N):
k = 2lg N - 1
while k >= 1:
for i in range(k,N):
x = A[i]
j = i-k
while j >= 0 and x < A[j]:
A[j+k] = A[j]
j -= k
A[j+k] = x
k = (k+1)/2 1
-
Sortowanie szybkie
Zaawansowane sortowanie przez zamian elementw
1. Podziel tablic A[p..r] na dwie A1[p..q] i A2[q+1..r],
takie, e kady element nalecy do A1 jest mniejszy
ni dowolny element A2
2. Posortuj A1 i A2
-
Quicksort - implementacja def QuickSort(A, l, r):
if (l < r) :
q = Partition(A, l, r)
QuickSort (A, l, q)
QuickSort (A, q+1, r)
QuickSort(Tablica, 0, MAX-1)
-
Partition
1. Wybieramy element x (granic podziau)
2. Idc od poczatku oprzedziau szukamy pierwszego
elementu wikszego lub rwnego ni x.
3. Idc od gry przedziau szukamy ostatniego
elementu mniejszego lub rwnego ni x
4. Zamieniamy znalezione elementy.
5. Koczymy gdy poszukiwania dotr to tego samego
elementu
6. Warunki brzegowe:
co bdzie gdy wybierzemy min/max w przedziale?
-
Partition - implementacja def Partition(A, l, r):
x = A[l]
i = l-1
j = r+1
while true:
while true:
j = j-1
if A[j] = x : break
if i
-
Randomized partition
Zapobiega umylnemu wygenerowaniu
najgorszego przypadku danych (ale dalej
moliwe jest wystpienie takiego przypadku)
def RandomPartition(A, l, r):
i = Random(l, r)
A[i],A[l] = A[l],A[i]
return Partition(A, l, q)
-
Qicksort - waciwoci redni czas O(N log N)
pesymistyczny czas O(N2)
prosty algorytm niewielki narzut
najgorszy przypadek:
Partition za kadym razem tworzy obszary
o rozmiarach N-1 i 1
Randomized Partition brak moliwoci podania
najgorszego przypadku
Aby zmniejszy ew. zajto stosu (w najgorszym przypadku
~N) mona wybiera do sortowania najpierw mniejszy
a potem wikszy z przedziaw (co najwyej log N)
Zachowanie uporzdkowania czciowego zaley od
implementacji funkcji Partition
-
Kopiec
Kady element jest nie mniejszy (wikszy) ni jego
dzieci
15
9 13
8 7 10 1
2 4 3
15 9 13 8 7 10 1 2 4 3
def Parent(i): return i/2
def Left(i): return i*2
def Right(i): return i*2+1
UWAGA index = 1..size
A[Parent(i)] >= A[i]
1
2 3
4 5 6 7
8 9 10
-
Przywracanie wasnoci kopca
Z: waciwo kopca moe nie by speniona tylko dla
korzenia
1) rozpocznij od korzenia (W=Root)
2) if jest speniona waciwo kopca dla W i synw:
koniec
else
zamie W z wikszym z synw W
powtrz 2) dla nowego W
-
Przywracanie w. kopca
15
5 14
10 4 9 3
2 8 1
15
10 14
5 4 9 3
2 8 1
15
10 14
8 7 9 3
2 5 1
1
2 3
4 5 6 7
8 9 10
1
2 3
4 5 6 7
8 9 10
1
2 3
4 5 6 7
8 9 10
-
Przywracanie wasnoci kopca def Heapify(A, i, size):
L = Left(i)
R = Right(i)
if LA[i-1]:
maxps = L
else:
maxps = i
if RA[maxps-1]:
maxps = R
if maxps != i:
A[i-1],A[maxps-1] = [maxps-1],A[i-1]
Heapify(A, maxps, size)
-
Sortowanie kopcowe
Tworzenie kopca z caej tablicy
Przywracamy wasno kopca dla coraz wikszych kopcw
Dla kolejnych (coraz mniejszych) kopcw Wybr najwikszego elementu (korze kopca),
Zamiana z ostatnim,
Zmniejszenie rozmiarw kopca,
Przywrcenie wasnoci kopca.
-
Budowa kopca 5 1 3 2 11 7 4 10 5 7
5
1 3
2 11 7 4
10 6 7
1
2 3
4 5 6 7
8 9 10
5
1 3
10 11 7 4
2 6 7
1
2 3
4 5 6 7
8 9 10
5
1 7
10 11 3 4
2 6 7
1
2 3
4 5 6 7
8 9 10
5
11 7
10 7 3 4
2 6 1
1
2 3
4 5 6 7
8 9 10
11
10 7
6 7 3 4
2 5 1
1
2 3
4 5 6 7
8 9 10
11 10 7 6 7 3 4 2 5 1
-
Sortowanie kopca 11 10 7 8 7 9 3 2 4 1 8 7 7 4 1 9 9 2 10 11
11
10 7
8 7 9 9
2 4 1
1
2 3
4 5 6 7
8 9 10
1
10 7
8 7 9 9
2 4 11
1
2 3
4 5 6 7
8 9
10
8 7
4 7 9 9
2 1 11
1
2 3
4 5 6 7
8 9
1
8 7
4 7 9 9
2 10 11
1
2 3
4 5 6 7
8
8
7 7
4 1 9 9
2 10 11
1
2 3
4 5 6 7
8
-
Sortowanie kopcowe def BuildHeap(A, size):
for i in range(size/2,0,-1):
Heapify(A, i, size)
def HeapSort(A, size):
BuildHeap(A, size)
for i in range(size-1,1,-1) :
A[i], A[0] = A[0], A[i]
Heapify(A, 1, i)
-
Sortowanie przez scalanie
nie jest wymagany dostp do wszystkich elementw
np. dla plikw, list
podzia cigu A -> B,C
scalenie B+C -> cig par
cig par - > B,C
scalenie B+C -> cig czwrek
cig czwrek - > B,C
scalenie B+C -> cig semek
.
-
Sortowanie przez scalanie we: 40, 60, 10, 45, 90, 20, 09, 72
podzia: (40) (60) (10) (45)
(90) (20) (09) (72)
scalanie: (40 90) (20 60) (09 10) (45 72)
podzia: (40 90) (20 60) (09 10) (45 72)
scalanie: (09 10 40 90) (20 45 60 72)
podzia : (09 10 40 90) (20 45 60 72)
scalanie: (09 10 20 40 45 60 72 90)
-
Kolejka priorytetowa
Przykad: zadania do wykonania, zamwienia
Wymagane operacje:
Dodaj element o priorytecie X
Pobierz element o najwyszym priorytecie
Przeczytaj element o najwyszym priorytecie (bez
usuwania)
Przy realizacji kolejki priorytetowej przy pomocy kopca
Zapis: dodawanie elementw do kopca
Odczyt: zwr A[0] i przebuduj kopiec
-
Dodawanie do kopca 1) dodaj nowy element w na koniec kopca
2) if jest speniona waciwo kopca dla W\
i ojca W:
koniec
else:
zamie W z ojcem W
powtrz 2) dla W i nowego ojca W
-
Dodawanie do kopca
13
10 7
6 7 3 4
2 5 1
1
2 3
4 5 6 7
8 9 10
11
13 10 7 6 7 3 4 2 5 1 11
7 13 11 7 6 10 3 4 2 5 1
13
11 7
6 10 3 4
2 5 1
1
2 3
4 5 6 7
8 9 10
7
-
Usunicie maksimum/minimum
Spostrzeenie: Maximum (Minimum) jest korze kopca
1) Usuwamy korze
2) Na miejsce korzenia wstawiamy ostatni
element kopca
3) Wykonujemy Heapify(Root)
-
Kolejka priorytetowa - realizacja def HeapInsert(A, size, newElement):
if size>=MAXSIZE:
ERROR przepelnienie kopca
else:
size=size+1
i = size
while i>1 and A[Parent(i)-1]
-
Kolejka priorytetowa - realizacja def HeapGetMax(A, size):
if size
-
Sortowanie liniowe?
Niekiedy dodatkowe informacje o kluczach
lub charakterze elementw umoliwiaj
sortowanie w czasie liniowym
-
Sortowanie przez zliczanie Czas liniowy
Zaoenie: wszystkie elementy s liczbami
z przedziau 0..maxN
maxN jest akceptowalnie due (tablica mieci si
w pamici komputera)
1) zlicz (w tablicy A) wystpienia poszczeglnych\
elementw
2) przygotuj tablice B z pocztkami sekwencji
B[] = 0
B[i] = B[i-1] + A[i-1]
3) przepisz elementy do nowej tablicy C na pozycj
C[B[element.klucz]++] = element
-
Sortowanie przez zliczanie def CountingSort(A, B, maxN, size):
for i in range(0, maxN+1):
C[i] = 0
for i in range(0, size):
C[A[i]] = C[A[i]]+1
# C[i] zawiera liczb elementw rwnych i
for i in range(1, maxN+1):
C[i] = C[i] + C[i-1]
# C[i] zawiera liczb elementw
-
Sortowanie przez zliczanie We I A[i] B[i] Wy
A3 0 0 0 E1
B2 1 2 0+1+1 I1
C3 2 2 2+1+1 B2
D5 3 2 4+1+1 F2
E1 4 2 6+1+1 A3
F2 5 1 8+1 C3
G4 6 0 9 G4
H4 7 0 9 H4
I1 8 0 9 D5
-
Sortowanie kubekowe Czas liniowy
Zaoenie: wszystkie klucze s liczbami (rzeczywistymi) z
przedziau x0 .. x1
Rwnomierny rozkad wartoci kluczy w przedziale
1) podziel dziedzin kluczy na n rwnych przedziaw
dugoci p = (x1 - x0) / n,
gdzie i-ty przedzia < x0+(i-1)*p , x0+i*p),
dla i = 1..n, a ostatni (pierwszy) przedzia jest
obustronnie domknity
2) przepisz n elementw do n list (kubekw), tak
aby elementy na i-tej miay klucze z nalece do
i-tego przedziau
3) Posortuj elementy w kubekach (dowolnym alg.)
4) Wypisz zawarto poszczeglnych kubekw od i = 1
do n
-
Wyszukiwanie maksimum def Minimum(A, size):
m = A[0]
for i in range(1,size):
if (m>A[i]): m=A[i]
return m
-
Wyszukiwanie min i maks def MinMax(A, size):
mi = A[0]
ma = A[0]
for i in range(2,size+2,2) :
if A[i]
-
Zwracanie kilku wartoci C/C++ struct MM {
ELEMENT min, max;
MM(ELEMENT emin, ELEMENT emax) {// konstruktor
Min = emin;
Max = emax;
}
};
MM Minmax(ELEMENT A[], INDEX size)
{
.....
return MM(min, max);
//bez konstruktora trzeba uy zmiennej
//chwilowej
}
-
Wyszukiwanie i-tej statystyki
Oczekiwany czas dziaania = O(n)
Pesymistyczny czas dziaania = O(n2)
def RandomizedSelect(A, i, l, r):
if l == r: return A[p]
q = RandomizedPartition(A, l, r)
k = ql+1
if i
-
Wyszukiwanie i-tej statystyki Pesymistyczny czas dziaania = O(n)
INDEX PartitionX(ELEMENT A[], INDEX p, INDEX r,
ELEMENT e)
ELEMENT Select(ELEMENT A[], INDEX p, INDEX r)
1. Podziel elementy p do q na n/5 grup po 5 elementw O(n)
2. Wyznacz median kadej z n/5 grup, sortujc je (czas stay). Jeli (ostatnia) ma parzyst liczb elementw wybierz wiksz z median
O(n)
3. Wywoaj rekurencyjnie x = Select(...) na zbiorze median
wyznaczonym w kroku 2 - b.d.
4. Podziel tablic A wzgldem mediany median tj. x i zmodyfikowanej
PartitionX. Niech wynik bdzie k - O(n)
5. Wywoaj rekurencyjnie Select(A, p, k) jeeli i
-
Wyszukiwanie i-tej statystyki
x
Uwagi:
Co najmniej poowa median jest wiksza rwna x
Co najmniej n/5 grup zawiera 3 elementy wiksze rwne x,
przy czym jedna z nich zawiera x, a druga moe by niepena
Std liczba elementw wiksza (mniejsza) od x wynosi co
najmniej 3 (1/2 n/5 - 2) 3n/10 - 6