Zobacz, to nie jest takie trudne. W sortowaniu przez dzielenie lub scalanie zwał jak zwał, chodzi o to że dzielisz jakiś dany zbiór na mniejsze i je “sortujesz”. Jest to po to że łatwiej (szybciej) posortować mniejszą ilość rzeczy lub scalić już posortowane dwie różne listy. Sortowanie w tym algorytmie odbywa się jakby od góry “stosu” rekurencyjnego. Przykład:
Mamy następującą listę liczb do posortowania:
1: (1, 0, -4, 5, 7, 6, 3)
dzielisz to teraz na dwie mniejsze listy, załóżmy że zaokrąglamy w dół czyli jedna ma 3 elementy druga 4:
2: (1, 0, -4) (5, 7, 6, 3)
teraz z każdą listą robisz dokładnie to samo
3: (1) (0, -4) (5, 7) (6, 3)
gdy mamy jedną liczbę w liście to nic z nią nie robimy a kolejne dzielimy dalej
4: (0) (-4) (5) (7) (6) (3)
teraz mamy sześć list po jednym elemencie i jedną również jednoelementową, ale w poziomie niżej. Niżej ponieważ dół tego drzewka jest jakby szczytem od którego zaczyna się sortowanie, szczytem - górą o której wspominałem wcześniej.
Gdy już mamy taką sytuację to te jednoelementowe listy łączymy ze sobą ustawiając ich elementy w kolejności rosnącej i taką listę zwracamy do poziomu niższego.
W najwyższym (4) poziomie nasze posortowane listy będą wyglądały następująco:
4: (-4, 0) (5, 7) (3, 6)
takie listy zwracamy do poziomu niższego (3) teraz sytuacja na tym etapie wyglądać będzie tak:
3: (1) (-4, 0) (5, 7) (3, 6)
znów łączymy listy biorąc np. pierwszy element z pierwszej listy i pierwszy z drugiej, porównujemy który jest niższy i zapisujemy go. Ponieważ listy już są posortowane to teraz jest tylko kwestia taka by połączyć te listy, będzie to wyglądało mniej więcej tak:
dla list - (1) oraz (-4, 0):
1 jest większa od -4 więc zapisuję -4 do nowej listy; nowa lista: (-4)
znów 1 porównuję z kolejnym elementem drugiej listy, czyli z 0, jedynka znów większa od zera więc dodaję zero; nowa lista: (-4, 0)
ponieważ nic nie mam w drugiej liście to wszystkie elementy w pierwszej są na pewno posortowane już i większe od wpisanych liczb do nowej listy więc spokojnie mogę ją przepisać, tak uzyskujemy wynik:
(-4, 0, 1)
dla list - (5, 7) oraz (3, 6)
porównujemy 5 i 3, zapisujemy 3; nowa lista: (3)
porównujemy 5 i 6, zapisujemy 5; nowa lista: (3, 5)
porównujemy 7 i 6, zapisujemy 6; nowa lista: (3, 5, 6)
koniec drugiej listy zapisujemy liczby z pierwszej; nowa lista: (3, 5, 6, 7)
zwracamy dwie listy i w poziomie 2 mamy zwrócone takie listy:
2: (-4, 0, 1) (3, 5, 6, 7)
porównujemy -4 i 3, zapisujemy -4; nowa lista (-4)
porównujemy 0 i 3, zapisujemy 0; nowa lista (-4, 0)
porównujemy -1 i 3, zapisujemy -4; nowa lista (-4, 0, 1)
doszliśmy do końca pierwszej listy można zapisać drugą bo jest posortowana; nowa lista (-4, 0, 1, 3, 5, 6, 7)
zwracamy listę, która właściwie jest naszym wynikiem
1: (-4, 0, 1, 3, 5, 6, 7)
Teraz najważniejsze, za każdym razem budując kolejny poziom wywołujemy tą samą funkcję (rekurencyjnie), ale wysyłając do niej mniejsze listy i dopiero gdy uzyskami jednoelementową listę to ją zwracamy, w ten sposób poziom niższy po prostu połączy dwie jednoelementowe listy, czyli sortowanie odbywa się w momencie łączenia listy.
Kolejna uwaga, nie jest nigdzie powiedziane że trzeba wywołać rekurencyjnie funkcję sortującą na jednoelementowej liście, można w tym momencie na podstawie tych elementów stworzyć nową listę. Będzie to wydajniejsze, ale taka implementacja nie pokaże w piękny sposób rekurencji w tym algorytmie, ona nadal będzie, będzie poprawna, lecz nie do końca przejrzysta dla osoby uczącej się.
Tak naprawdę to to co rozpisałem w komputerze tak nie będzie działało. Będzie to wyglądało tak że najpierw zostanie rozwinięta gałąź dla lewej listy a dopiero potem dla prawej, będzie tak dla każdej kolejnej listy.
A na koniec skoro masz już działający algorytm to tutaj masz ode mnie moim zdaniem prościej napisane, uważam że łatwiej będzie Ci zrozumieć na podstawie tego kodu. Oczywiście jest tutaj kilka rzeczy do poprawy, np. wyodrębnienie fragmentu scalania dwóch tablic do osobnej funkcji, nie zrobiłem tego specjalnie byś poczuł o co chodzi, kolejną rzeczą mogłaby być optymalizacja. Zamiast tworzyć nowe tablice i przepisywać do nich wartości lepiej byłoby przekazywać cały czas tą samą, ale z ograniczeniami jakie próbowałeś stosować, czyli początek i koniec, trzeba jednak przy tym pamiętać że inaczej będzie wyglądał algorytm scalania. Nie będzie można bezpośrednio przepisywać wartości do sortowanej tablicy lecz trzeba będzie użyć jakieś dodatkowej zmiennej tymczasowej. Myślę że powinieneś wiedzieć o co chodzi, a jak nie poczytaj o zamianie wartości dwóch zmiennych, gdy masz zmienną a = 3 i b =7 jak zrobić by a = 7 natomiast b = 3.
http://ideone.com/4zc1OT
Co do tego co napisał @kostek135
Polecam uważniejsze czytanie, nie rozumiem po co znajduje się tam 90% rzeczy, ponieważ całość można napisać dużo prościej. Dodatkowo nie jestem fanem dawania rozwiązań zadań szkolnych zwłaszcza takich które czegoś uczą.
Pewne rzeczy które wskazałeś jako błąd nie były błędne. Wszystko zależało od implementacji i akurat wskazałeś błąd który w implementacji autora nie był nim, dopiero gdy wprowadziłeś swoje zmiany stał się błędem.