Programowanie w VB Proste algorytmy sortowania Sortowanie

Transkrypt

Programowanie w VB Proste algorytmy sortowania Sortowanie
Programowanie w VB
Proste algorytmy sortowania
Sortowanie bąbelkowe
Algorytm sortowania bąbelkowego polega na porównywaniu par elementów leżących obok siebie i,
jeśli jest to potrzebne, zmienianiu ich kolejności. Czyli w pierwszym przebiegu porównujemy (i
ewentualnie zamieniamy):
• Element pierwszy i drugi
• Element drugi i trzeci
• ...
• Element (n-1)-wszy i n-ty
Każdy element jest tak długo przesuwany w ciągu, aż napotkany zostanie element większy od niego,
wtedy w następnych krokach przesuwany jest ten większy element.
Po pierwszym przebiegu ciąg nie musi być jeszcze uporządkowany, ale na pozycji n znajdzie się
maksymalny element ciągu. Zatem w drugim przebiegu można porządkować ciąg krótszy, czyli tylko
elementy na pozycjach od 1 do n-1. Po drugim przebiegu, dwa ostatnie elementy są na swoich
miejscach, czyli pozostaje posortować ciąg o dwa elementy krótszy, itd.
Można jeszcze bardziej usprawnić ten algorytm. Jeżeli w pewnym przebiegu algorytmu ostatnia
zamiana nastąpiła na pozycji i, to w następnym przebiegu wystarczy porządkować tylko elementy na
pozycjach od 1 do i-1. W takiej wersji ten algorytm jest zrealizowany w demonstracji.
Jeżeli dane wejściowe są uporządkowane, to algorytm wykonuje tylko jeden przebieg (nie jest
wykonywana żadna zamiana).
Option Base 1
Const N = 10
Const MAXVALUE = 20
Dim a(N) As Integer
Sub SortBubble()
Dim i As Integer, j As Integer, v As Integer
For i = 1 To N
For j = 1 To N - i
If a(j) > a(j + 1) Then
v = a(j)
a(j) = a(j + 1)
a(j + 1) = v
End If
Next j
Next i
End Sub
Sortowanie przez wstawianie
W algorytmie sortowania przez wstawianie ciąg danych jest dzielony na dwie części:
• już uporządkowaną (przed uruchomieniem procedury nie zawiera ona żadnych elementów),
• jeszcze nie uporządkowaną (na początku zawiera wszystkie elementy).
Sposób porządkowania można opisać następująco:
1. weź pierwszy element z części nieuporządkowanej (jeśli jest pusta to zakończ działanie
algorytmu),
2. wstaw go w odpowiednie miejsce w części uporządkowanej (po takiej operacji część
nieuporządkowana jest jeden element krótsza, a część posortowana zyskuje jeden element).
Pozostaje jeszcze do rozstrzygnięcia, w jaki sposób wyznaczyć prawidłowe położenie nowego
elementu w części uporządkowanej. Najprostszy sposób polega na porównaniu tego elementu z
kolejnymi elementami części uporządkowanej. Jeżeli element na pozycji i jest większy od
wstawianego, to ten nowy element należy wstawić między elementy na pozycjach i-1 i i.
Inna strategia wstawiania elementu do uporządkowanego ciągu jest zastosowana w sortowaniu
przez wstawianie z binarnym umieszczaniem.
Algorytm ten działa w czasie pesymistycznym 1/2 N^2 - O(N), oczekiwanym 1/4 N^2 + O(N). Ilość
wykonanych porównań jest równa liczbie inwersji, tzn. takich par że a[i] > a[j] dla i < j, zatem działa
bardzo szybko dla tablic niemal uporządkowanych. Algorytm ten jest stabilny, prosty i łatwo
implementowalny.
Option Base 1
Const N = 10
Const MAXVALUE = 20
Dim a(N) As Integer
' Znajdowanie indeksu dla nowej wartosci v w tablicy
posortowanej rosnaco
' algorytm iteracyjny
Function SearchIdxIter(ByVal l As Integer, ByVal p As
Integer, ByVal v As Integer) As Integer
Dim k As Integer
For k = l To p
If a(k) >= v Then
Exit For
End If
Next k
SearchIdxIter = k
End Function
' Znajdowanie indeksu dla nowej wartosci v w tablicy
posortowanej rosnaco
' iteracyjny algorytm przeszukiwania binarnego
Function SearchIdxBinIter(ByVal l As Integer, ByVal p As
Integer, ByVal v As Integer) As Integer
Dim k As Integer
While p - l >= 0
If a(l) >= v Then
SearchIdxBinIter = l
Exit Function
End If
If a(p) < v Then
SearchIdxBinIter = p + 1
Exit Function
End If
k = (l + p) \ 2
If a(k) < v Then
l=k+1
Else
p=k
End If
Wend
End Function
Sub SortInsertBinIter()
Dim i As Integer, j As Integer, k As Integer, v As Integer
For i = 2 To N
v = a(i)
k = SearchIdxBinIter(1, i - 1, v)
If k < i Then
For j = i To k + 1 Step -1
a(j) = a(j - 1)
Next j
a(k) = v
End If
Next i
End Sub
Sub SortInsertBinRek()
Dim i As Integer, j As Integer, k As Integer, v As Integer
For i = 2 To N
v = a(i)
k = SearchIdxBinRek(1, i - 1, v)
If k < i Then
For j = i To k + 1 Step -1
a(j) = a(j - 1)
Next j
a(k) = v
End If
Next i
End Sub
Sub SortInsertIter()
Dim i As Integer, j As Integer, k As Integer, v As Integer
For i = 2 To N
v = a(i)
k = SearchIdxIter(1, i - 1, v)
If k < i Then
For j = i To k + 1 Step -1
a(j) = a(j - 1)
Next j
a(k) = v
End If
Next i
End Sub
' Znajdowanie indeksu dla nowej wartosci v w tablicy
posortowanej rosnaco
' rekurencyjny algorytm przeszukiwania binarnego
Function SearchIdxBinRek(ByVal l As Integer, ByVal p As
Integer, ByVal v As Integer) As Integer
Dim k As Integer
If a(l) >= v Then
SearchIdxBinRek = l
Exit Function
End If
If a(p) < v Then
SearchIdxBinRek = p + 1
Exit Function
End If
If p <= l + 1 Then
SearchIdxBinRek = p
Exit Function
End If
k = (l + p) \ 2
If a(k) < v Then
SearchIdxBinRek = SearchIdxBinRek(k, p, v)
Else
SearchIdxBinRek = SearchIdxBinRek(l, k, v)
End If
End Function
Sortowanie przez selekcję
Jest to chyba najbardziej intuicyjny algorytm sortowania. Polega on na wielokrotnym wyborze
minimalnego elementu z coraz krótszego podciągu danych. Dokładnie ma to następujący przebieg:
• Wybierz minimum z ciągu elementów na pozycjach od 1 do n i zamień go z pierwszym
elementem.
• Wybierz minimum z ciągu elementów na pozycjach od 2 do n i zamień go z drugim elementem
(po tym kroku elementy na pozycjach od 1 do 2 są uporządkowane).
• ...
• Wybierz minimum z ciągu elementów na pozycjach n-1 i n i zamień go z elementem na pozycji
n-1 (po tej operacji elementy na pozycjach od 1 do n-1 są uporządkowane, a element na
pozycji n jest maksymalny, czyli ciąg elementów na pozycjach od 1 do n jest uporządkowany)
Znalezienie minimum w ciągu wymaga m-1 porównań, gdzie m jest długością ciągu. Algorytm
sortowania przez wybór wykonuje n-1 takich operacji, a długość ciągu, z którego wybierany jest
element minimalny zmienia się od n do 2.
Option Base 1
Const N = 10
Const MAXVALUE = 20
Dim a(N) As Integer
' Znajdowanie indeksu najmniejszego elementu w tablicy nieposortowanej
Function SearchIdxMin(ByVal l As Integer, ByVal p As Integer) As Integer
Dim Min As Integer, k As Integer
SearchIdxMin = l
Min = a(l)
For k = l + 1 To p
If a(k) < Min Then
SearchIdxMin = k
Min = a(k)
End If
Next k
End Function
Sub SortSelection()
Dim i As Integer, v As Integer
For i = 1 To N - 1
v = a(i)
k = SearchIdxMin(i, N)
a(i) = a(k)
a(k) = v
Next i
End Sub
Algorytm ten działa w czasie stałym 1/2 N^2 - O(N); zawsze wykonujemy ten sam ciąg porównań.
Algorytm ten dokonuje tylko N-1 przestawień. Algorytm ten nie jest stabilny.
Sortowanie szybkie
W przypadku tej metody sortowania jest wykorzystywana strategia "dziel i zwyciężaj". Jest to bardzo
efektywna technika algorytmiczna (wykorzystana jest także w algorytmie sortowania przez scalanie).
Przypuśćmy, że potrafimy podzielić dany ciąg na dwie takie części, że elementy pierwszego ciągu są
mniejsze od elementów drugiego ciągu, czyli nieformalnie mówiąc, na elementy "małe" i "duże".
Mając taki podział ciągu, możemy każdą z części uporządkować osobno (pomińmy na razie, w jaki
sposób to zrobić). Otrzymamy ciąg składający się z uporządkowanych elementów "małych", a po
nich następują uporządkowane elementy "duże" - czyli cały ciąg jest już uporządkowany!
Algorytm służący do dzielenia ciągu na dwie części, spełniające opisany warunek, ma następującą
postać:
• Weź pierwszy element ciągu (oznaczmy go przez x).
• Podziel ciąg tak, aby w pierwszej części znalazły się elementy mniejsze lub równe x, a w
drugiej większe lub równe x
Można teraz podać pełny algorytm sortujący:
• Jeżeli liczba elementów w ciągu jest większa od 1, to podziel ciąg na dwie części tak, aby
elementy z pierwszej części były nie większe niż elementy z drugiej części.
• Wywołaj procedurę sortującą dla pierwszej części ciągu.
• Wywołaj procedurę sortującą dla drugiej części ciągu.
Dla poprawności działania powyższego algorytmu nie ma znaczenia, który element zostanie wybrany
jako element rozdzielający ciąg na dwie części. Ma to jednak wpływ na efektywność algorytmu. W
naszym przypadku wybierany jest element środkowy.
Czas działania tego algorytmu sortowania zależy od wielkości podziałów wykonywanych przez
procedurę dzielącą ciąg. Jeżeli podziały te są zrównoważone, czyli wielkości powstających części są
sobie równe, to algorytm ten jest praktycznie najszybszą metodą sortowania – stąd jego nazwa:
sortowanie szybkie (ang. quicksort). Jeżeli natomiast otrzymane w wyniku podziału ciągi mają bardzo
różne długości, to złożoność algorytmu jest większa.
Option Base 1
Const N = 10
Const MAXVALUE = 20
Dim a(N) As Integer
Sub QuickSort(ByVal l As Integer, ByVal p As Integer)
Dim v As Integer, i As Integer, j As Integer, temp As Integer
v = a((l + p) \ 2)
i=l
j=p
Do
While a(i) < v
i=i+1
Wend
While v < a(j)
j=j-1
Wend
If i <= j Then
temp = a(i)
a(i) = a(j)
a(j) = temp
i=i+1
j=j-1
End If
Loop While i <= j
If l < j Then
QuickSort l, j
End If
If i < p Then
QuickSort i, p
End If
End Sub