Merge sort je podobný algoritmu rychlého třídění, protože pracuje na konceptu rozděl a panuj. Je to jeden z nejpopulárnějších a nejúčinnějších třídicích algoritmů. Je to nejlepší příklad pro kategorii algoritmů rozděl a panuj.
Rozdělí daný seznam na dvě poloviny, zavolá se pro obě poloviny a poté obě seřazené poloviny spojí. Definujeme spojit() funkce sloužící ke sloučení dvou polovin.
Podseznamy se znovu a znovu dělí na poloviny, dokud nezískáme každý jediný prvek. Potom zkombinujeme pár seznamů jednoho prvku do dvou seznamů prvků a v procesu je seřadíme. Seřazené dva páry prvků se sloučí do čtyř seznamů prvků a tak dále, dokud nezískáme setříděný seznam.
Sloučit koncept řazení
Podívejme se na následující schéma řazení sloučení.
Uvedený seznam jsme rozdělili na dvě poloviny. Seznam nelze rozdělit na stejné části, to vůbec nevadí.
Slučovací řazení lze implementovat dvěma způsoby – přístupem shora dolů a přístupem zdola nahoru. Ve výše uvedeném příkladu používáme přístup shora dolů, což je nejčastěji používané řazení Merge.
Přístup zdola nahoru poskytuje více optimalizace, kterou definujeme později.
Hlavní částí algoritmu je to, jak kombinujeme dva seřazené podseznamy. Pojďme sloučit dva seřazené slučovací seznamy.
- A: [ 2 , 4, 7, 8]
- B: [ 1 , 3, 11]
- seřazeno: prázdné
Nejprve pozorujeme první prvek obou seznamů. Zjistíme, že první prvek B je menší, takže jej přidáme do našeho setříděného seznamu a posuneme se vpřed v seznamu B.
- A: [ 2 , 4, 7, 8]
- B: [1, 3 , jedenáct]
- Seřazeno: 1
Nyní se podíváme na další dvojici prvků 2 a 3. 2 je menší, takže jej přidáme do našeho seřazeného seznamu a přesuneme se vpřed na seznam.
- A: [ 2 , 4, 7, 8]
- B: [1, 3 , jedenáct]
- Seřazeno: 1
Pokračujte v tomto procesu a skončíme se seřazeným seznamem {1, 2, 3, 4, 7, 8, 11}. Mohou nastat dva speciální případy.
modem vs router
Co když mají oba podseznamy stejné prvky - V takovém případě můžeme přesunout jeden podseznam a přidat prvek do seřazeného seznamu. Technicky se můžeme posouvat vpřed v obou dílčích seznamech a přidávat prvky do seřazeného seznamu.
V jednom dílčím seznamu nám nezbyl žádný prvek. Když vyčerpáme v dílčím seznamu prvek, jednoduše přidáme prvek druhého po sobě.
Měli bychom si pamatovat, že prvek můžeme seřadit v libovolném pořadí. Daný seznam seřadíme vzestupně, ale můžeme snadno seřadit sestupně.
Implementace
Algoritmus řazení sloučení je implementován pomocí přístupu shora dolů. Může to vypadat trochu obtížně, takže podrobně propracujeme každý krok. Zde implementujeme tento algoritmus na dva typy kolekcí – celočíselný seznam prvků (obvykle používaný k zavedení třídění) a vlastní objekt (praktičtější a realističtější scénář).
Pole řazení
Hlavním konceptem algoritmu je rozdělení (pod)seznamu na poloviny a jejich rekurzivní třídění. Pokračujeme v procesu, dokud neskončíme se seznamy, které mají pouze jeden prvek. Pojďme pochopit následující funkci pro dělení -
def merge_sort(array, left_index, right_index): if left_index >= right_index: return middle = (left_index + right_index)//2 merge_sort(array, left_index, middle) merge_sort(array, middle + 1, right_index) merge(array, left_index, right_index, middle)
Naším hlavním cílem je rozdělit seznam na podčásti, než dojde k třídění. Potřebujeme získat celočíselnou hodnotu, takže pro naše indexy použijeme operátor //.
Pojďme pochopit výše uvedený postup pomocí následujících kroků.
- Prvním krokem je vytvoření kopií seznamů. První seznam obsahuje seznamy z [left_index,...,middle] a druhý z [middle+1,?,right_index] .
- Obě kopie seznamu projdeme pomocí ukazatele, vybereme menší hodnotu ze dvou hodnot a přidáme je do seřazeného seznamu. Jakmile přidáme prvek do seznamu a bez ohledu na to se posouváme vpřed v seřazeném seznamu.
- Přidejte zbývající prvky v druhé kopii do seřazeného pole.
Pojďme implementovat slučovací řazení v programu Python.
Program Python
# Here, we are declaring the function to divide the lists in to the two sub lists # Here, we are passing the list1, left index, right index as the parameters def merge_sort(list1, left_index, right_index): if left_index >= right_index: # here, we are checking the if condition return middle = (left_index + right_index)//2 # Here, we are finding the middle of the given two numbers merge_sort(list1, left_index, middle) # Here, we are calling the merge sort function till the middle number we got merge_sort(list1, middle + 1, right_index) # Here, we are calling the merge sort function till the end of the list i.e., right index merge(list1, left_index, right_index, middle) # Here, we are calling the merge function to merge the divided list using the merge # sort function above # Here, we are defining a function for merge the list after dividing def merge(list1, left_index, right_index, middle): # Here, we are creating subparts of a lists left_sublist = list1[left_index:middle + 1] right_sublist = list1[middle+1:right_index+1] # Here, we are initializing the values for variables that we use to keep # track of where we are in each list1 left_sublist_index = 0 right_sublist_index = 0 sorted_index = left_index # Here, we are traversing the both copies until we get run out one element while left_sublist_index <len(left_sublist) 1 and right_sublist_index < len(right_sublist): # here, we are declaring a while loop if our left_sublist has the smaller element, put it in sorted part then move forward (by increasing pointer) left_sublist[left_sublist_index] checking condition, is true will enter block list1[sorted_index]="left_sublist[left_sublist_index]" left_sublist_index="left_sublist_index" + otherwise add into right sublist else: moving sorted_index="sorted_index" go through remaining elements them len(left_sublist): len(right_sublist):# list1="[44," 65, 2, 3, 58, 14, 57, 23, 10, 1, 7, 74, 48] print('the given list before performing merge sort is: ', list1) this input unsorted array by user merge_sort(list1, 0, len(list1) -1) after is:', printing amd functions pre> <p> <strong>Output:</strong> </p> <pre> The given list before performing the merge sort is: [44, 65, 2, 3, 58, 14, 57, 23, 10, 1, 7, 74, 48] The given list after performing the merge sort is: [1, 2, 3, 7, 10, 14, 23, 44, 48, 57, 58, 65, 74] </pre> <h2>Sorting Custom Objects</h2> <p>We can also sort the custom objects by using the <a href="/python-tutorial-python-programming-language">Python</a> class. This algorithm is almost similar to the above but we need to make it more versatile and pass the comparison function.</p> <p>We will create a custom class, Car and add a few fields to it. We make few changes in the below algorithm to make it more versatile. We can do this by using the lambda functions.</p> <p>Let's understand the following example.</p> <h3>Python Program</h3> <pre> class Car: # here, we are declaring a class named car def __init__(self, make, model, year): self.make = make # Here, we are using the self to declare the make variables locally self.model = model # Here, we are using the self to declare the model variables locally self.year = year # Here, we are using the self to declare the year variables locally def __str__(self): return str.format('Make: {}, Model: {}, Year: {}', self.make, self.model, self.year) # Here, we are returning the format of the strings given def merge(list1, l, r, m, comp_fun): # Here, we are defining a function for merge the list using the compound function left_copy = list1[l:m + 1] # here, we are coping the left part of the list r_sublist = list1[m+1:r+1] # here, we are coping the right part of the list left_copy_index = 0 # here, we are coping the left part indexes of the list r_sublist_index = 0 # here, we are coping the right part indexes of the list sorted_index = l while left_copy_index <len(left_copy) 1 and r_sublist_index < len(r_sublist): # here, we are declaring a while loop using the comp_fun instead of simple comparison operator if comp_fun(left_copy[left_copy_index], r_sublist[r_sublist_index]): checking condition, it is true then will enter block list1[sorted_index]="left_copy[left_copy_index]" left_copy_index="left_copy_index" + else: condition false else sorted_index="sorted_index" len(left_copy): <len(r_sublist): def merge_sort(list1, l, r, comp_fun): merge sort function to given list l>= r: # Here, we are checking the if condition, if it is true then we will enter the block return m = (l + r)//2 # here, we are finding the middle element of the list merge_sort(list1, l, m, comp_fun) # Here, we are calling the merge sort function till the middle number we got merge_sort(list1, m + 1, r, comp_fun) # Here, we are calling the merge sort function from the middle number we got merge(list1, l, r, m, comp_fun) # Here, we are calling the merge function to merge the divided list using the merge # sort function above car1 = Car('Renault', '33 Duster', 2001) car2 = Car('Maruti', 'Maruti Suzuki Dzire', 2015) car3 = Car('Tata motor', 'Jaguar', 2004) car4 = Car('Cadillac', 'Seville Sedan', 1995) list1 = [car1, car2, car3, car4] merge_sort(list1, 0, len(list1) -1, lambda carA, carB: carA.year <carb.year) print('cars sorted by year:') for car in list1: # here, we are declaring the loop to iterate through list1 print(car) printing all data of and list print() merge_sort(list1, 0, len(list1) -1, lambda cara, carb: cara.make < carb.make) make:') pre> <p> <strong>Output:</strong> </p> <pre> Cars sorted by year: Make: Cadillac, Model: Seville Sedan, Year: 1995 Make: Renault, Model: 33 Duster, Year: 2001 Make: Tata motor, Model: Jaguar, Year: 2004 Make: Maruti, Model: Maruti Suzuki Dzire, Year: 2015 Cars sorted by make: Make: Cadillac, Model: Seville Sedan, Year: 1995 Make: Maruti, Model: Maruti Suzuki Dzire, Year: 2015 Make: Renualt, Model: 33 Duster, Year: 2001 Make: Tata motor, Model: Jaguar, Year: 2004 </pre> <h2>Optimization</h2> <p>We can improve the performance of the merge sort algorithm. First let's understand the difference between the top-down and bottom-up merge sort. The bottom-up approach sorts the elements of adjacent lists iteratively where the top-down approach breaks down the lists into the two halves.</p> <p>The given list is [10, 4, 2, 12, 1, 3], instead of breaking it down into [10], [4], [2], [12], [1], [3] - we divide into the sub lists which may already sorted: [10, 4], [2], [1, 12], [3] and now are ready to sort them.</p> <p>Merge sort is inefficient algorithm in both time and space for the smaller sub lists. So, insertion sort is more efficient algorithm than the merge sort for the smaller sub lists.</p> <h2>Conclusion</h2> <p>Merge sort is popular and efficient algorithm. It is more efficient algorithm for the large lists. It does not depend on the any unfortunate decisions that lead to bad runtimes.</p> <p>There is one major demerit in the merge sort. It uses the additional memory that is used to store the temporary copies of lists before merging them. However Merge sort is widely used in the software. Its performance is fast and produces the excellent result.</p> <p>We have discussed the merge sort concept in brief and implement it both on simple integer list and on custom objects via a lambda function used for comparison.</p> <hr></carb.year)></len(left_copy)></pre></len(left_sublist)>
Třídění vlastních objektů
Můžeme také třídit vlastní objekty pomocí Krajta třída. Tento algoritmus je téměř podobný výše uvedenému, ale musíme jej učinit všestrannějším a předat porovnávací funkci.
Vytvoříme vlastní třídu Car a přidáme k ní několik polí. V níže uvedeném algoritmu jsme provedli několik změn, aby byl všestrannější. Můžeme to udělat pomocí funkcí lambda.
Pojďme pochopit následující příklad.
co je obj v javě
Program Python
class Car: # here, we are declaring a class named car def __init__(self, make, model, year): self.make = make # Here, we are using the self to declare the make variables locally self.model = model # Here, we are using the self to declare the model variables locally self.year = year # Here, we are using the self to declare the year variables locally def __str__(self): return str.format('Make: {}, Model: {}, Year: {}', self.make, self.model, self.year) # Here, we are returning the format of the strings given def merge(list1, l, r, m, comp_fun): # Here, we are defining a function for merge the list using the compound function left_copy = list1[l:m + 1] # here, we are coping the left part of the list r_sublist = list1[m+1:r+1] # here, we are coping the right part of the list left_copy_index = 0 # here, we are coping the left part indexes of the list r_sublist_index = 0 # here, we are coping the right part indexes of the list sorted_index = l while left_copy_index <len(left_copy) 1 and r_sublist_index < len(r_sublist): # here, we are declaring a while loop using the comp_fun instead of simple comparison operator if comp_fun(left_copy[left_copy_index], r_sublist[r_sublist_index]): checking condition, it is true then will enter block list1[sorted_index]="left_copy[left_copy_index]" left_copy_index="left_copy_index" + else: condition false else sorted_index="sorted_index" len(left_copy): <len(r_sublist): def merge_sort(list1, l, r, comp_fun): merge sort function to given list l>= r: # Here, we are checking the if condition, if it is true then we will enter the block return m = (l + r)//2 # here, we are finding the middle element of the list merge_sort(list1, l, m, comp_fun) # Here, we are calling the merge sort function till the middle number we got merge_sort(list1, m + 1, r, comp_fun) # Here, we are calling the merge sort function from the middle number we got merge(list1, l, r, m, comp_fun) # Here, we are calling the merge function to merge the divided list using the merge # sort function above car1 = Car('Renault', '33 Duster', 2001) car2 = Car('Maruti', 'Maruti Suzuki Dzire', 2015) car3 = Car('Tata motor', 'Jaguar', 2004) car4 = Car('Cadillac', 'Seville Sedan', 1995) list1 = [car1, car2, car3, car4] merge_sort(list1, 0, len(list1) -1, lambda carA, carB: carA.year <carb.year) print(\'cars sorted by year:\') for car in list1: # here, we are declaring the loop to iterate through list1 print(car) printing all data of and list print() merge_sort(list1, 0, len(list1) -1, lambda cara, carb: cara.make < carb.make) make:\') pre> <p> <strong>Output:</strong> </p> <pre> Cars sorted by year: Make: Cadillac, Model: Seville Sedan, Year: 1995 Make: Renault, Model: 33 Duster, Year: 2001 Make: Tata motor, Model: Jaguar, Year: 2004 Make: Maruti, Model: Maruti Suzuki Dzire, Year: 2015 Cars sorted by make: Make: Cadillac, Model: Seville Sedan, Year: 1995 Make: Maruti, Model: Maruti Suzuki Dzire, Year: 2015 Make: Renualt, Model: 33 Duster, Year: 2001 Make: Tata motor, Model: Jaguar, Year: 2004 </pre> <h2>Optimization</h2> <p>We can improve the performance of the merge sort algorithm. First let's understand the difference between the top-down and bottom-up merge sort. The bottom-up approach sorts the elements of adjacent lists iteratively where the top-down approach breaks down the lists into the two halves.</p> <p>The given list is [10, 4, 2, 12, 1, 3], instead of breaking it down into [10], [4], [2], [12], [1], [3] - we divide into the sub lists which may already sorted: [10, 4], [2], [1, 12], [3] and now are ready to sort them.</p> <p>Merge sort is inefficient algorithm in both time and space for the smaller sub lists. So, insertion sort is more efficient algorithm than the merge sort for the smaller sub lists.</p> <h2>Conclusion</h2> <p>Merge sort is popular and efficient algorithm. It is more efficient algorithm for the large lists. It does not depend on the any unfortunate decisions that lead to bad runtimes.</p> <p>There is one major demerit in the merge sort. It uses the additional memory that is used to store the temporary copies of lists before merging them. However Merge sort is widely used in the software. Its performance is fast and produces the excellent result.</p> <p>We have discussed the merge sort concept in brief and implement it both on simple integer list and on custom objects via a lambda function used for comparison.</p> <hr></carb.year)></len(left_copy)>
Optimalizace
Můžeme zlepšit výkon algoritmu řazení sloučení. Nejprve pochopíme rozdíl mezi řazením sloučení shora dolů a zdola nahoru. Přístup zdola nahoru iterativně třídí prvky sousedních seznamů, kde přístup shora dolů rozděluje seznamy na dvě poloviny.
Uvedený seznam je [10, 4, 2, 12, 1, 3], místo toho, abychom jej rozebrali na [10], [4], [2], [12], [1], [3] - dělíme do podseznamů, které již mohou být seřazeny: [10, 4], [2], [1, 12], [3] a nyní jsou připraveny je seřadit.
Sloučit řazení je neefektivní algoritmus v čase i prostoru pro menší dílčí seznamy. Řazení vkládání je tedy efektivnější algoritmus než slučovací řazení pro menší podseznamy.
Závěr
Merge sort je populární a efektivní algoritmus. Je to efektivnější algoritmus pro velké seznamy. Nezáleží na žádných nešťastných rozhodnutích, která vedou ke špatným runtimem.
Sloučení má jednu hlavní nevýhodu. Využívá přídavnou paměť, která se používá k ukládání dočasných kopií seznamů před jejich sloučením. V softwaru se však široce používá řazení Merge. Jeho výkon je rychlý a poskytuje vynikající výsledek.
Stručně jsme diskutovali o konceptu řazení sloučení a implementovali jej jak na jednoduchý celočíselný seznam, tak na vlastní objekty pomocí funkce lambda používané pro srovnání.