• Nie Znaleziono Wyników

Wyznaczamy najmniejszy element w ciągu (tablicy) i zamieniamy go miejscami z elementem pierwszym, następnie z pozostałego ciągu wybieramy element najmniejszy i ustawiamy go na drugie miejsce tablicy (zmieniamy), itd. Realizacja w C++

N/A
N/A
Protected

Academic year: 2021

Share "Wyznaczamy najmniejszy element w ciągu (tablicy) i zamieniamy go miejscami z elementem pierwszym, następnie z pozostałego ciągu wybieramy element najmniejszy i ustawiamy go na drugie miejsce tablicy (zmieniamy), itd. Realizacja w C++"

Copied!
18
0
0

Pełen tekst

(1)

Idea:

Wyznaczamy najmniejszy element w ciągu (tablicy) i zamieniamy go miejscami z elementem pierwszym, następnie z pozostałego ciągu wybieramy element najmniejszy i ustawiamy go na drugie miejsce tablicy (zmieniamy), itd.

Realizacja w C++

void selekcja (int a[],int l, int r) {

for (int i=l; i<r; i++) {

int min=i;

for (int j=i+1; j<=r; j++) if (a[j]<a[min]) min=j;

zamiana(a[i],a[min]);

} }

//realizacja funkcji zamiana //przestawiajacej dwa elementy //dowolnego typu

void zamiana(int &A, int &B) {

int t=A;

A=B;

B=t;

}

Typ może być dowolny

(2)

Przykład:

S E L E K C J A 7 porównań

A E L E K C J S 6 porównań

A C L E K E J S 5 porównań

A C E L K E J S 4 porównania

A C E E K L J S 3 porównania

A C E E J K L S 2 porównania

A C E E J K L S 1 porównanie

(3)

Analiza:

Załóżmy, że l=0 i r=n-1.

W linii pierwszej przykładu mamy n-1 porównań a[j]<a[min], potem w kolejnych liniach: n-2, n-3, ….a na końcu tylko 1 porównanie. Zatem:

) ( )

1 (

1 2

...

) 2 (

) 1

( n   n     

1(2n1)

n  

n(n21)

12

n

2

O n

Tmax(n) P-stwo, że w każdym z

porównań znajdziemy element najmniejszy jest jednakowe

2 ) 1 ( 2

) 1

, (

, 1 , 2 , ,

) 1 (

2

1

 

n n n n

k

n

k

n

p n

Stąd:

)

2

(

4 2 1 4 1 4

1 2 1 4

) 1 ( 2

2 ) 1 ( 2

1 ) 1 (

2 1

) 1 (

2 )

1 (

2 1

, 1

2 ) 1 2 (

) 1 ( 2

) 1 ( 2

) 1 (

n O n

n n

k k

p k

n n

n n n

n k

n n n

n k

k n k

n n n

n n

n n

n

(4)

Policzmy teraz pesymistyczną wrażliwość tego algorytmu. Przypomnijmy, że

Ponieważ w procedurze zawsze jest wykonywany ten sam ciąg operacji, niezależnie od danych wejściowych, to Δ(n)=0.

Obliczmy na koniec miarę wrażliwości oczekiwanej algorytmu.

0 )

( n

w procedurze zawsze jest wykonywany ten sam ciąg operacji, niezależnie od danych wejściowych

Ponadto S(n)=O(1) Mówimy, że algorytm sortuje w miejscu

(5)

Zalety:

a) Liczba zamian w najgorszym przypadku: n-1.

b) Prostota implementacji.

c) Zadowalająca szybkość dla małych wartości n.

d) Nie wymaga dodatkowej pamięci.

Wady:

a) Nie jest stabilny.

b) Ma dużą złożoność (rzędu kwadratowego), więc nie nadaje się do sortowania długich tablic.

c) Jest mało wrażliwy na wstępne uporządkowanie.

Algorytm można uczynić stabilnym, zwiększając współczynnik proporcjonalności złożoności.

(6)

Idea:

W i-tym kroku trzeba wstawić element tab[i] na właściwe miejsce w posortowanym fragmencie tab[0]…tab[i-1], wcześniej przesuwając wszystkie elementy większe od niego w tym fragmencie w prawo o 1;

powstaje posortowany fragment tab[0]…tab[i+1].

Realizacja w C++

void InsertSort(int *tab) {

for(int i=1; i<n;i++) {

int j=i; // 0..i-1 jest już posortowane int temp=tab[j];

while ((j>0) && (tab[j-1]>temp)) {

tab[j]=tab[j-1];

j--;

}

tab[j]=temp;

} }

(7)

W S T A W I A N I E 1 porównanie

S W T A W I A N I E <=2 porównania

S T W A W I A N I E <=3 porównania

A S T W W I A N I E <= 4 porównania

A S T W W I A N I E <=5 porównań

A I S T W W A N I E …….

A A I S T W W N I E …….

A A I N S T W W I E …….

A A I N N S T W W E <=9 porównań

A A E I N N S T W W GOTOWE

(8)

Analiza:

W linii pierwszej mamy 1 porównanie, potem maksymalnie 2, itd. , aż do maksymalnie n-1 porównań na końcu. Zatem możemy policzyć

pesymistyczną złożoność :

) ( )

1 (

) 2 (

2 1 )

(

( 2 1) 2

m ax

n n n n

T         

n n

 

Ponieważ element tab[i] z równym prawdopodobieństwem może

zająć każdą z i-tej pozycji w ciągu tab[0]<tab[1]<…<tab[i-1], to w i-tym kroku mamy pij=1/i, czyli

. )

...

2 1 ( )

(

1 1 12 12

1 1 1

i i

i i

i

j i i

j

ij

sr

i j p j i i

T

  

Sumując teraz po wszystkich n-1 iteracjach, dostajemy:

).

( )

1 (

) ...

3 2

( )

1 (

) ( )

(

2 2

2 2 1

2 1 2

2 1 1

1 2 1 1

1 2

1 1

1

n n

n k

i i

T n

T

n

n

k n

i n

i i n

i

sr sr

  

(9)

Jest to zatem kres górny zbioru liczb, które powstają jako różnice ilości operacji dominujących. Zatem od liczby największej z

możliwych należy odjąć najmniejszą z możliwych, żeby otrzymać taki kres górny.

Ponieważ najmniejszą ilością porównań w każdym kroku n-1iteracji jest jedno porównanie, a największa ilość wyrażą się obliczoną

właśnie Tmax(n)=n(n-1)/2 to = =n(n-1)/2-(n-1)=Θ(n2).

Policzmy teraz pesymistyczną wrażliwość tego algorytmu. Przypomnijmy, że

Pesymistyczna wrażliwość złożoności czasowej jest zatem duża i możemy się spodziewać dużej zmienności złożoności

obliczeniowej.

(10)

Średnia wrażliwość (czyli miara wrażliwości oczekiwanej): w i-tym kroku mamy:

).

( ...

) 1 2

( )

( )

(

16 23

1 ...

1 1...

2 4

1 1

...

1

2

i j i n n

n

n

i j i

i n

i

 

 

  

   

i j i i

j

i i i

j

śr

i p

ij

j j i

T j

i

...

1

2 4

1 ...

1

2 1 2 1 ...

1

2

2

( ) ( ( )) ( ) ( 2 1 )

Sumując po wszystkich n-1 iteracjach, dostajemy:

(11)

Zalety:

a) Stabilność.

b) Średnio algorytm jest 2 razy szybszy niż algorytm sortowania przez selekcję.

c) Optymalny dla ciągów prawie posortowanych.

d) Nie wymaga dodatkowej pamięci.

(12)

Udoskonalenia:

•Można przestać porównywać elementy, napotkawszy element, który jest nie większy niż wstawiany, bo podtablica z lewej strony jest posortowana – sortowanie adaptacyjne.

•W pierwszej pętli „for” wyznaczamy element najmniejszy i umieszczamy go na początku tablicy, następnie sortujemy pozostałe elementy.

•Standardowo sortuje się zamiany elementów, ale można zrobić przeniesienie większych elementów o jedną pozycję w prawo.

(13)

Ma prosty zapis.

Na czym polega to sortowanie? Przykład 7-elementowej tablicy.

Element zacieniowany w pojedynczym przebiegu głównej pętli „ulatuje” do góry jako najlżejszy.

Tablica jest przemiatana od dołu do góry (pętla i) i analizowane są dwa

sąsiadujące ze sobą

elementy (pętla j); jeśli nie są uporządkowane, to następuje ich zamiana.

(14)

void bubble(int *tab) {

for (int i=1;i<n;i++)

for (int j=n-1;j>=i;j--) if (tab[j]<tab[j-1])

{//swap

int tmp=tab[j-1];

tab[j-1]=tab[j];

tab[j]=tmp;

} }

Implementacja w C++

Analiza:

•Dość często zdarzają się puste przebiegi(nie jest dokonywana żadna wymiana, bo elementy są posortowane).

•Algorytm jest bardzo wrażliwy na konfigurację danych:

4,2,6,18,20,39,40 – wymaga jednej zamiany 4,6,18,20,39,40,2 – wymaga szesściu zamian

Algorytm jest klasy O(n2)

(15)

void bubble(int *tab) {

for (int i=1;i<n;i++)

for (int j=n-1;j>=i;j--) if (tab[j]<tab[j-1])

{//swap

int tmp=tab[j-1];

tab[j-1]=tab[j];

tab[j]=tmp;

} }

Ulepszenia: przyśpieszają, choć nie zmieniają klasy.

•Można zapamiętać indeks ostatniej zamiany (walka z pustymi przebiegami).

•Można przełączać kierunki przeglądania tablicy (walka z niekorzystnymi konfiguracjami danych). void ShakerSort(int *tab)

{

int left=1,right=n-1,k=n-1;

do {

for(int j=right; j>=left; j--) if(tab[j-1]>tab[j])

{

swap(tab[j-1],tab[j]);

k=j;

} left=k+1;

for(j=left; j<=right; j++) if(tab[j-1]>tab[j])

{

swap(tab[j-1],tab[j]);

k=j;

} right=k-1;

}

while (left<=right);

}

Algorytm poprawiony – sortowania przez wstrząsanie.

(16)

Idea:

Jest to również metoda „dziel i rządź”,

ponieważ dzieli tablicę na dwie części, które potem sortuje niezależnie.

Algorytm składa się z dwóch kroków:

Krok 1: procedura rozdzielania elementów tablicy względem wartości pewnej komórki tablicy służącej za oś podziału; proces

sortowania jest dokonywany przez tę właśnie procedurę.

Krok 2: procedura służąca do właściwego sortowania, która nie robi w zasadzie nic oprócz wywoływania samej siebie; zapewnia poskładanie wyników cząstkowych i w

konsekwencji posortowanie całej tablicy.

(17)

Sednem metody jest proces podziału, który zmienia

kolejność elementów w tablicy tak, że spełnione są trzy

warunki:

• element a[i] znajduje się dla pewnego i na właściwej pozycji w tablicy;

•Żaden z elementów a[l], …, a[i-1] nie jest większy niż a[i];

•Żaden z elementów a[i+1],

…, a[r] nie jest mniejszy niż

a[i]. W kółku mamy element

rozgraniczający, elementy mniejsze są na lewo, a większe na prawo.

(18)

Oś podziału

Cytaty

Powiązane dokumenty

W przypadku podania błędnej danej skrypt ma wyświetlić komunikat ”Bledne dane!” Dla wczytanej cyfry 1 skrypt ma obliczać sumę 2 liczb wczytanych z klawiatury. 2 tak, aby

jeśli wybrany wierzchołek nie ma potomstwa, które jeszcze nie zostało dopisane do ciągu, to nadaj mu etykietę „zamknięty”, w przeciwnym przypadku dopisz do ciągu

Założenie: najefektywniejsze rozwiązanie stosu za pomocą tablicy – szczyt stosu to ostatni element wstawiony tablicy począwszy od miejsca o indeksie 0 (jeśli liczba elementów

Założenie: najefektywniejsze rozwiązanie stosu za pomocą tablicy – szczyt stosu to ostatni element wstawiony tablicy począwszy od miejsca o indeksie 0 (jeśli liczba elementów

Zadania powtórzeniowe do drugiego kolokwium z podstaw logiki.

dimming pełne podświetlenie LED ze strefowym wygaszaniem gdzie za ekranem umieszczona jest cała ściana diod, które mogą być strefowo wygaszane w pewnych miejscach ekranu

[r]

Suma trzech pierwszych wyrazów ciągu