Algorytm sortowania przez scalanie

Sortowanie przez scalanie polega na wielokrotnym dzieleniu na połowy tablicy zawierającej dane przeznaczone do uporządkowania.

Kiedy wszystkie tablice będą zawierać jeden element, następuje ich łączenie.

Dane pochodzące z dwóch tablic są zapisywane w ustalonym porządku (niemalejąco lub nierosnąco).

Proces łączenia tablic trwa do momentu, w którym pozostanie tylko jedna tablica.

Przykładowe zadanie typu maturalnego

Zadanie 1. Hodowla owiec

W miejscowości Rekursja działa farma zajmująca się hodowlą owiec. W gospodarstwie znajduje się 10 000 zwierząt. Każda owca jest oznaczona unikalnym numerem z zakresu (0, 100 000).

Zadanie 1.1

Co roku odbywa się strzyżenie owiec. Przeprowadzane jest przez dziesięć zespołów. Owce są prowadzone z pastwiska na miejsce strzyżenia w kolejności losowej: pierwsza przyprowadzona owca trafia do pierwszego zespołu, druga do drugiego; jedenasta owca znów do pierwszego zespołu i tak dalej. W ramach poszczególnych zespołów owce są strzyżone w kolejności zgodnej z ich oznaczeniami, zaczynając od najmniejszego numeru.

Napisz program, który przydzieli owce do poszczególnych zespołów oraz określi kolejność strzyżenia owiec w ramach zespołów.

W pliku owce.txt zapisano 10 000 liczb całkowitych z przedziału (0, 100 000), każdą w nowej linii – są to identyfikatory owiec; kolejność w pliku odzwierciedla kolejność, w której owce są sprowadzane z pastwiska na miejsce strzyżenia.

R18BcpW0eHDlB

Plik do pobrania zawiera tekst.

Plik TXT o rozmiarze 67.28 KB w języku polskim

Przykładowe dane:

Linia 1. 50270. Linia 2. 51360. Linia 3. 59263.

Do oceny oddajesz:

  • plik wyniki.txt zawierający odpowiedź (identyfikatory owiec podzielone na 10 grup zgodnie z treścią zadania, posortowane niemalejąco w obrębie grup; każda grupa powinna być oddzielona pojedynczą pustą linią)

  • plik(i) z komputerową realizacją zadania (kodem programu)

Rozwiązanie przedstawimy w postaci pseudokodu, ponieważ na egzaminie maturalnym można korzystać z samodzielnie wybranego języka programowania: C++, Java lub Python.

Praca domowa

Przedstaw rozwiązanie zadania w postaci programu w języku C++, Java lub Python. Zadbaj o prawidłowe wczytanie danych z pliku tekstowego do programu. Odpowiedź do zadania znajdziesz w osobnym pliku umieszczonym po omówieniu pseudokodu.

Rozwiązanie

Na początek zauważmy, że opisany sposób podziału owiec pomiędzy zespoły zajmujące się strzyżeniem to nic innego jak przyporządkowanie na podstawie reszty z dzielenia przez 10. Nadajmy zespołom numery od 0 do 9. Uznajmy również, że będziemy numerować linie w pliku wejściowym od 0. Dzięki temu możemy powiedzieć, że wszystkie owce o identyfikatorach znajdujących się w liniach, których reszta z dzielenia przez 10 wynosi 0, powinny być strzyżone przez zespół o numerze 0. Wszystkie owce o identyfikatorach znajdujących się w liniach, których reszta z dzielenia przez 10 wynosi 1, powinny być strzyżone przez zespół o numerze 1 itd.

Zaczniemy pseudokod od wczytania pliku z danymi do dwuwymiarowej tablicy zespolyOwce. Tablica miała tyle tyle wierszy, ile jest zespołów (10) oraz tyle kolumn, ile wynosi liczba owiec n przez liczbę zespołów (czyli 1000). Zakładamy, że operator % to operator modulo (reszty z dzielenia), a operator // to dzielenie całkowitoliczbowe.

Linia 1. n znak równości 10000. Linia 2. liczbaZespolow znak równości 10. Linia 3. zespolyOwce otwórz nawias kwadratowy liczbaZespolow zamknij nawias kwadratowy otwórz nawias kwadratowy n prawy ukośnik prawy ukośnik liczbaZespolow zamknij nawias kwadratowy. Linia 5. dla i znak równości 0 przecinek 1 przecinek kropka kropka kropka przecinek n minus 1 wykonuj dwukropek. Linia 6. zespol znak równości i procent liczbaZespolow. Linia 7. miejsceWTtablicy znak równości i prawy ukośnik prawy ukośnik liczbaZespolow. Linia 8. zespolyOwce otwórz nawias kwadratowy zespol zamknij nawias kwadratowy otwórz nawias kwadratowy miejsceWTtablicy zamknij nawias kwadratowy znak równości i minus ty wiersz pliku cudzysłów owce kropka txt cudzysłów.

Będziemy sortować tak przygotowane dane. Każdy wiersz tablicy zespolyOwce będziemy sortować oddzielnie z użyciem algorytmu sortowania przez scalanie.

Linia 1. dla i znak równości 0 przecinek 1 przecinek kropka kropka kropka przecinek liczbaZespolow minus 1 wykonuj dwukropek. Linia 2. sortowanieScalanie otwórz nawias okrągły zespolyOwce otwórz nawias kwadratowy i zamknij nawias kwadratowy przecinek 1 przecinek n prawy ukośnik prawy ukośnik liczbaZespolow zamknij nawias okrągły.

Wewnątrz pętli wywołujemy funkcję realizującą algorytm sortowania przez scalanie. Jako dane wejściowe podajemy: tablicę z numerami owiec – czyli wiersz dwuwymiarowej tablicy, indeks komórkiindeks komórkiindeks komórki, od której rozpoczniemy sortowanie oraz indeks komórki, na której zakończymy sortowanie.

Gdy już wszystkie wiersze zostaną posortowane, pozostaje zapisać dane do pliku wyjściowego zgodnie z treścią zadania: kolejnymi grupami, a między każdą grupą powinien znaleźć się jeden pusty wiersz.

Linia 1. dla i znak równości 0 przecinek 1 przecinek kropka kropka kropka przecinek liczbaZespolow minus 1 wykonuj dwukropek. Linia 2. dla j znak równości 0 przecinek 1 przecinek kropka kropka kropka przecinek n prawy ukośnik prawy ukośnik liczbaZespolow minus 1 wykonuj dwukropek. Linia 3. wypisz zespolyOwce otwórz nawias kwadratowy i zamknij nawias kwadratowy otwórz nawias kwadratowy j zamknij nawias kwadratowy do pliku cudzysłów wyniki kropka txt cudzysłów. Linia 4. wypisz pustą linię do pliku cudzysłów wyniki kropka txt cudzysłów.

Przeanalizujmy algorytm sortujący.

Linia 1. funkcja sortowanieScalanie otwórz nawias okrągły owce otwórz nawias kwadratowy zamknij nawias kwadratowy przecinek lewy przecinek prawy zamknij nawias okrągły. Linia 2. jeżeli lewy zamknij nawias ostrokątny znak równości prawy wykonaj dwukropek. Linia 3. zakończ. Linia 4. środek znak równości otwórz nawias okrągły lewy plus prawy zamknij nawias okrągły prawy ukośnik prawy ukośnik 2. Linia 5. sortowanieScalanie otwórz nawias okrągły owce przecinek lewy przecinek środek zamknij nawias okrągły. Linia 6. sortowanieScalanie otwórz nawias okrągły owce przecinek środek plus 1 przecinek prawy zamknij nawias okrągły. Linia 7. scal otwórz nawias okrągły owce przecinek lewy przecinek środek przecinek prawy zamknij nawias okrągły.
  1. Definujemy funkcję, która będzie dzielić tablicę na części. [linia 1]

  2. Sprawdzamy, czy tablica, która ma zostać podzielona, nie jest tablicą jednoelementową (jeżeli tak jest, kończymy bieżące wywołanie rekurencyjnerekurencjarekurencyjne funkcji). [linie 2, 3]

  3. Wyznaczamy środek podziału tablicy. [linia 4]

  4. Wywołujemy funkcję sortowania przez scalanie dla utworzonych podtablic. [linie 5, 6]

  5. Scalamy jednoelementowe tablice. [linia 7]

Linia 1. funkcja scal otwórz nawias okrągły owce otwórz nawias kwadratowy zamknij nawias kwadratowy przecinek lewy przecinek środek przecinek prawy zamknij nawias okrągły. Linia 2. długośćL znak równości środek minus lewy. Linia 3. długośćP znak równości prawy minus środek. Linia 4. dla i znak równości 1 przecinek 2 przecinek kropka kropka kropka długośćL wykonuj dwukropek. Linia 5. lewaPom otwórz nawias kwadratowy i zamknij nawias kwadratowy znak równości owce otwórz nawias kwadratowy lewy plus i zamknij nawias kwadratowy. Linia 6. dla i znak równości 1 przecinek 2 przecinek kropka kropka kropka długośćP wykonuj dwukropek. Linia 7. prawaPom otwórz nawias kwadratowy i zamknij nawias kwadratowy znak równości owce otwórz nawias kwadratowy środek plus i plus 1 zamknij nawias kwadratowy. Linia 8. x znak równości 1. Linia 9. y znak równości 1. Linia 10. z znak równości lewy. Linia 11. dopóki otwórz nawias okrągły x otwórz nawias ostrokątny długośćL ampersant ampersant y otwórz nawias ostrokątny długośćP zamknij nawias okrągły wykonuj dwukropek. Linia 12. jeżeli lewaPom otwórz nawias kwadratowy x zamknij nawias kwadratowy otwórz nawias ostrokątny znak równości prawaPom otwórz nawias kwadratowy y zamknij nawias kwadratowy wykonaj dwukropek. Linia 13. owce otwórz nawias kwadratowy z zamknij nawias kwadratowy znak równości lewaPom otwórz nawias kwadratowy x zamknij nawias kwadratowy. Linia 14. x znak równości x plus 1. Linia 15. jeżeli lewaPom otwórz nawias kwadratowy x zamknij nawias kwadratowy zamknij nawias ostrokątny prawaPom otwórz nawias kwadratowy y zamknij nawias kwadratowy wykonaj dwukropek. Linia 16. owce otwórz nawias kwadratowy z zamknij nawias kwadratowy znak równości prawaPom otwórz nawias kwadratowy y zamknij nawias kwadratowy. Linia 17. y znak równości y plus 1. Linia 18. z znak równości z plus 1. Linia 19. dopóki x otwórz nawias ostrokątny lewy wykonuj dwukropek. Linia 20. owce otwórz nawias kwadratowy z zamknij nawias kwadratowy znak równości lewaPom otwórz nawias kwadratowy x zamknij nawias kwadratowy. Linia 21. x znak równości x plus 1. Linia 22. z znak równości z plus 1. Linia 23. dopóki y otwórz nawias ostrokątny prawy wykonuj dwukropek. Linia 24. owce otwórz nawias kwadratowy z zamknij nawias kwadratowy znak równości prawaPom otwórz nawias kwadratowy y zamknij nawias kwadratowy. Linia 25. y znak równości y plus 1. Linia 26. z znak równości z plus 1. Linia 27. zakończ.
  1. Definiujemy funkcję scalania, która będzie zapisywać elementy pochodzące z dwóch podtablic w jednej tablicy z zachowaniem odpowiedniej kolejności. [linia 1]

  2. Ustalamy długości podtablic, a następnie zapisujemy je w zmiennych pomocniczych. Musimy pamiętać, że podział jest umowny – nie tworzyliśmy nowych tablic danych, a zatem cały czas przetwarzamy tablicę Owce. Aby nie utracić danych z oryginalnej tablicy, musimy umieścić sortowaną część w tablicach pomocniczych. [linie od 2 do 7]

  3. Tworzymy zmienne pomocnicze i ustawiamy ich wartość na 1 (w przedstawionym kodzie indeksy komórek tablicy zaczynają się od 1). [linie od 8 do 10]

  4. Dopóki podtablice zawierają elementy, które nie znajdują się w scalonej tablicy, wykonywane są następne kroki. [linia 11]

  5. Porównujemy kolejne wartości z podtablic i ustawiamy je w kolejności od najmniejszej do największej w pierwotnej tablicy. Wartość x inkrementujemyinkrementacjainkrementujemy po wpisaniu danych z tablicy lewaPom do pierwotnej tablicy. Tak samo postępujemy w przypadku wartości y (dla tablicy prawaPom). [linie od 11 do 17]

  6. Inkrementujemy wartość zmiennej z, która przechowuje indeks komórki pierwotnej tablicy, do której powinniśmy wpisać dane. [linia kodu 18]

  7. Jeżeli zdarzy się, że wyczerpiemy dane z jednej podtablicy, wpisujemy resztę danych z drugiej podtablicy do końca jej długości, a następnie kończymy działanie funkcji. [linie od 19 do 27]

Odpowiedź dla danych zapisanych w pliku tekstowym:

Rb3gUBRJMfO3G

Plik do pobrania zawiera tekst.

Plik TXT o rozmiarze 57.52 KB w języku polskim
Ćwiczenie 1
R1LUvscCBpjqL
Wymyśl pytanie na kartkówkę związane z tematem materiału.

Zadanie 1.2

Starsze owce przechodzą rutynowe badania kontrolne co 2 lata. Każdego roku jedna połowa owiec jest kierowana na badania. Druga połowa jest badana w kolejnym roku. W latach nieparzystych badania przechodzą tylko owce mające nieparzystą liczbę lat. Podobnie jest w przypadku lat parzystych i owiec mających parzystą liczbę lat. Owce badane są w kolejności od najstarszej do najmłodszej.

W 2012 roku przebadanych zostanie 2000 owiec.

Napisz program, który wyznaczy, w jakiej kolejności zwierzęta zostaną przebadane.

W pliku owce do badania.txt zapisano dane na temat wieku 2000 owiec. W każdej linii znajduje się liczba naturalna – wiek owcy w miesiącach.

RJuTWb8tS0Ifw

Plik do pobrania zawiera tekst.

Plik TXT o rozmiarze 9.67 KB w języku polskim

Do oceny oddajesz:

  • plik weterynarz.txt zawierający odpowiedź (oznaczenia owiec, zakwalifikowanych do badań w 2012 r.; kolejne wyniki zapisane w pliku powinny zgadzać się z kolejnością opisaną w zadaniu)

  • plik(i) z komputerową realizacją zadania (kodem programu)

Rozwiązanie przedstawimy w postaci pseudokodu, ponieważ na egzaminie maturalnym można korzystać z samodzielnie wybranego języka programowania: C++, Java lub Python.

Praca domowa

Przedstaw rozwiązanie zadania w postaci programu w języku C++, Java lub Python. Zadbaj o prawidłowe wczytanie danych z pliku tekstowego do programu. Odpowiedź do zadania znajdziesz w osobnym pliku umieszczonym za omówieniem pseudokodu.

Ważne!

Przy sprawdzaniu parzystości wieku, uwzględnij tylko skończone lata.

Rozwiązanie

Podczas rozwiązywania zadania skorzystamy ze zmodyfikowanej wersji kodu z zadania 1.1.

W tym przypadku nie sortujemy wszystkich danych. Musimy zatem zapisać interesujące nas informacje do osobnej tabeli, a następnie odpowiednio posortować jej zawartość.

Linia 1. owce otwórz nawias kwadratowy zamknij nawias kwadratowy znak równości cudzysłów owce do badania kropka txt cudzysłów. Linia 2. długośćTablicy znak równości 2000. Linia 3. owceDoBadania znak równości doBadania otwórz nawias okrągły owce przecinek długośćTablicy zamknij nawias okrągły. Linia 4. długośćTablicyOwceDoBadania znak równości długość tablicy owceDoBadania. Linia 5. sortowanieScalanie otwórz nawias okrągły owceDoBadania przecinek 1 przecinek długośćTablicyOwceDoBadania zamknij nawias okrągły. Linia 6. dla i znak równości 0 przecinek 1 przecinek kropka kropka kropka długośćTablicy minus 1 wykonuj dwukropek. Linia 7. wypisz owceDoBadania otwórz nawias kwadratowy i zamknij nawias kwadratowy.
  • Wywołujemy funkcję doBadania(), która zapisze interesujące nas dane w nowej tablicy owceDoBadania. [linia 3]

  • Pozostałe operacje zapisane w głównej części kodu są takie same jak te z zadania 1.1.

Linia 1. funkcja doBadania otwórz nawias okrągły owce otwórz nawias kwadratowy zamknij nawias kwadratowy przecinek długośćTablicy zamknij nawias okrągły. Linia 2. x znak równości 1. Linia 3. dla i znak równości 0 przecinek 1 przecinek kropka kropka kropka długośćTablicy minus 1 wykonuj dwukropek. Linia 4. jeżeli otwórz nawias okrągły otwórz nawias okrągły owce otwórz nawias kwadratowy i zamknij nawias kwadratowy minus otwórz nawias okrągły owce otwórz nawias kwadratowy i zamknij nawias kwadratowy procent 12 zamknij nawias okrągły zamknij nawias okrągły prawy ukośnik prawy ukośnik 12 zamknij nawias okrągły procent 2 znak równości znak równości 0 wykonaj dwukropek. Linia 5. owceDoBadania otwórz nawias kwadratowy x zamknij nawias kwadratowy znak równości owce otwórz nawias kwadratowy i zamknij nawias kwadratowy. Linia 6. x znak równości x plus 1. Linia 7. zwróć owceDoBadania.
  1. Definiujemy funkcję, która zapisze dane spełniające warunki zadania w tablicy owceDoBadania. [linia 1]

  2. Zapisujemy indeks komórki tablicy owceDoBadania, w której będą przechowywane kolejne dane [linia 2]

  3. Odczytujemy kolejne komórki tablicy owce i wpisujemy do tablicy owceDoBadania te spośród nich, które odpowiadają parzystemu wiekowi zwierząt (liczonemu w latach). Aby ustalić wiek owcy z uwzględnieniem tylko skończonych lat (ignorując pozostałe miesiące), zaczynamy od wyznaczenia reszty z dzielenia wieku owcy podanego w miesiącach przez 12 (liczbę miesięcy, które nie składają się na pełne lata). Wynik odejmujemy od wieku liczonego w miesiącach i dzielimy przez 12, aby wyznaczyć wiek w latach. Następnie sprawdzamy, czy jest on parzysty. [linia 4]

  4. Jeżeli wiek jest parzysty, wpisujemy go do tablicy owceDoBadania i inkrementujemy wartość x (wskazujemy indeks następnej komórki). [linie 5, 6]

Linia 1. sortowanieScalanie otwórz nawias okrągły owceDoBadania otwórz nawias kwadratowy zamknij nawias kwadratowy przecinek lewy przecinek prawy zamknij nawias okrągły. Linia 2. jeżeli lewy zamknij nawias ostrokątny znak równości prawy wykonaj dwukropek. Linia 3. zakończ. Linia 4. środek znak równości otwórz nawias okrągły lewy plus prawy zamknij nawias okrągły prawy ukośnik prawy ukośnik 2. Linia 5. sortowanieScalanie otwórz nawias okrągły owceDoBadania przecinek lewy przecinek środek zamknij nawias okrągły. Linia 6. sortowanieScalanie otwórz nawias okrągły owceDoBadania przecinek środek plus 1 przecinek prawy zamknij nawias okrągły. Linia 7. scal otwórz nawias okrągły owceDoBadania przecinek lewy przecinek środek przecinek prawy zamknij nawias okrągły.
  • Definicja funkcji sortowanieScalanie() jest taka sama jak zadaniu 1.1.

Linia 1. scal otwórz nawias okrągły owceDoBadania otwórz nawias kwadratowy zamknij nawias kwadratowy przecinek lewy przecinek środek przecinek prawy zamknij nawias okrągły. Linia 2. długośćL znak równości środek minus lewy. Linia 3. długośćP znak równości prawy minus środek. Linia 4. dla i znak równości 1 przecinek 2 przecinek kropka kropka kropka długośćL wykonuj dwukropek. Linia 5. lewaPom otwórz nawias kwadratowy i zamknij nawias kwadratowy znak równości owceDoBadania otwórz nawias kwadratowy lewy plus i zamknij nawias kwadratowy. Linia 6. dla i znak równości 1 przecinek 2 przecinek kropka kropka kropka długośćP wykonuj dwukropek. Linia 7. prawaPom otwórz nawias kwadratowy i zamknij nawias kwadratowy znak równości owceDoBadania otwórz nawias kwadratowy środek plus i plus 1 zamknij nawias kwadratowy. Linia 8. x znak równości 1. Linia 9. y znak równości 1. Linia 10. z znak równości 1. Linia 11. dopóki otwórz nawias okrągły x otwórz nawias ostrokątny długośćL ampersant ampersant y otwórz nawias ostrokątny długośćP zamknij nawias okrągły wykonuj dwukropek. Linia 12. jeżeli lewaPom otwórz nawias kwadratowy x zamknij nawias kwadratowy zamknij nawias ostrokątny znak równości prawaPom otwórz nawias kwadratowy y zamknij nawias kwadratowy wykonaj dwukropek. Linia 13. owceDoBadania otwórz nawias kwadratowy z zamknij nawias kwadratowy znak równości lewaPom otwórz nawias kwadratowy x zamknij nawias kwadratowy. Linia 14. x znak równości x plus 1. Linia 15. jeżeli lewaPom otwórz nawias kwadratowy x zamknij nawias kwadratowy otwórz nawias ostrokątny prawaPom otwórz nawias kwadratowy y zamknij nawias kwadratowy wykonaj dwukropek. Linia 16. owceDoBadania otwórz nawias kwadratowy z zamknij nawias kwadratowy znak równości prawaPom otwórz nawias kwadratowy y zamknij nawias kwadratowy. Linia 17. y znak równości y plus 1. Linia 18. z znak równości z plus 1. Linia 19. dopóki x otwórz nawias ostrokątny lewy wykonuj dwukropek. Linia 20. owceDoBadania otwórz nawias kwadratowy z zamknij nawias kwadratowy znak równości lewaPom otwórz nawias kwadratowy x zamknij nawias kwadratowy. Linia 21. x znak równości x plus 1. Linia 22. z znak równości z plus 1. Linia 23. dopóki y otwórz nawias ostrokątny prawy wykonuj dwukropek. Linia 24. owceDoBadania otwórz nawias kwadratowy z zamknij nawias kwadratowy znak równości prawaPom otwórz nawias kwadratowy y zamknij nawias kwadratowy. Linia 25. y znak równości y plus 1. Linia 26. z znak równości z plus 1. Linia 27. zakończ.
  • Modyfikujemy funkcję scal() tak, aby zapisywała ona wartości od największej do najmniejszej. Zamieniamy w tym celu znaki mniejszości (<) na znaki większości (>) i odwrotnie. [linie 12, 15]

Odpowiedź dla danych zawartych w pliku tekstowym:

R1ZvAqJtI280N

Plik do pobrania zawiera tekst.

Plik TXT o rozmiarze 2.82 KB w języku polskim
Ćwiczenie 2
R2TUGFPHSSAn2
Wymyśl pytanie na kartkówkę związane z tematem materiału.

Słownik

indeks komórki
indeks komórki

oznaczenie (numer) pozycji elementu w tablicy

inkrementacja
inkrementacja

zwiększenie wartości o 1

rekurencja
rekurencja

metoda programowania w dowolnym języku, polegająca na wywołaniu przez funkcję samej siebie; rekurencję można porównać do pętli, ponieważ jest ona wywoływana określoną liczbę razy (do momentu, gdy zajdzie warunek stopu)