Le tri par fusion est similaire à l'algorithme de tri rapide car il fonctionne sur le concept de diviser pour régner. C'est l'un des algorithmes de tri les plus populaires et les plus efficaces. C’est le meilleur exemple de la catégorie d’algorithmes diviser pour mieux régner.
Il divise la liste donnée en deux moitiés, s'appelle pour les deux moitiés puis fusionne les deux moitiés triées. Nous définissons le fusionner() fonction utilisée pour fusionner deux moitiés.
Les sous-listes sont divisées encore et encore en moitiés jusqu'à ce que nous obtenions chacune un seul élément. Ensuite, nous combinons la paire de listes d'éléments en deux listes d'éléments, en les triant au cours du processus. Les deux paires d'éléments triées sont fusionnées dans les listes de quatre éléments, et ainsi de suite jusqu'à ce que nous obtenions la liste triée.
Concept de tri de fusion
Voyons le diagramme de tri de fusion suivant.
Nous avons divisé la liste donnée en deux moitiés. La liste ne peut pas être divisée en parties égales, cela n'a aucune importance.
Le tri par fusion peut être mis en œuvre de deux manières : approche descendante et approche ascendante. Nous utilisons l'approche descendante dans l'exemple ci-dessus, qui est le tri par fusion le plus souvent utilisé.
L'approche ascendante apporte davantage d'optimisation que nous définirons plus tard.
La partie principale de l'algorithme est la façon dont nous combinons les deux sous-listes triées. Fusionnons les deux listes de fusion triées.
- UN : [ 2 , 4, 7, 8]
- B : [ 1 , 3, 11]
- trié : vide
Tout d’abord, nous observons le premier élément des deux listes. Nous trouvons que le premier élément du B est plus petit, nous l'ajoutons donc dans notre liste triée et avançons dans la liste B.
- UN : [ 2 , 4, 7, 8]
- B : [1, 3 , onze]
- Trié : 1
Examinons maintenant la paire suivante d'éléments 2 et 3. 2 est plus petit, nous l'ajoutons donc à notre liste triée et passons à la liste.
- UN : [ 2 , 4, 7, 8]
- B : [1, 3 , onze]
- Trié : 1
Continuez ce processus et nous nous retrouvons avec la liste triée de {1, 2, 3, 4, 7, 8, 11}. Il peut y avoir deux cas particuliers.
objet de tableau en Java
Que se passe-t-il si les deux sous-listes contiennent les mêmes éléments - Dans ce cas, nous pouvons déplacer l'une ou l'autre des sous-listes et ajouter l'élément à la liste triée. Techniquement, nous pouvons avancer dans les deux sous-listes et ajouter les éléments à la liste triée.
Il ne nous reste aucun élément dans une sous-liste. Lorsque nous manquons d'éléments dans une sous-liste, ajoutez simplement l'élément de la seconde l'un après l'autre.
Nous devons nous rappeler que nous pouvons trier les éléments dans n'importe quel ordre. Nous trions la liste donnée par ordre croissant mais nous pouvons facilement trier par ordre décroissant.
Mise en œuvre
L'algorithme de tri par fusion est implémenté en utilisant l'approche descendante. Cela peut sembler un peu difficile, nous allons donc détailler chaque étape. Ici, nous allons implémenter cet algorithme sur deux types de collections : une liste d'éléments entiers (généralement utilisée pour introduire le tri) et un objet personnalisé (un scénario plus pratique et réaliste).
Tableau de tri
Le concept principal de l'algorithme est de diviser la (sous) liste en moitiés et de les trier de manière récursive. Nous continuons le processus jusqu'à ce que nous obtenions des listes ne comportant qu'un seul élément. Comprenons la fonction suivante pour la division -
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)
Notre objectif principal est de diviser la liste en sous-parties avant le tri. Nous devons obtenir la valeur entière, nous utilisons donc l'opérateur // pour nos indices.
Comprenons la procédure ci-dessus en suivant les étapes.
- La première étape consiste à créer des copies de listes. La première liste contient les listes de [index_gauche,...,milieu] et le deuxième de [milieu+1,?,right_index] .
- Nous parcourons les deux copies de la liste à l'aide du pointeur, sélectionnons la plus petite valeur des deux valeurs et les ajoutons à la liste triée. Une fois que nous ajoutons l’élément à la liste, nous avançons malgré tout dans la liste triée.
- Ajoutez les éléments restants de l'autre copie au tableau trié.
Implémentons le tri par fusion dans le programme Python.
Programme 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)>
Tri des objets personnalisés
Nous pouvons également trier les objets personnalisés en utilisant le Python classe. Cet algorithme est presque similaire à celui ci-dessus mais nous devons le rendre plus polyvalent et passer la fonction de comparaison.
Nous allons créer une classe personnalisée, Car et y ajouter quelques champs. Nous apportons quelques modifications à l'algorithme ci-dessous pour le rendre plus polyvalent. Nous pouvons le faire en utilisant les fonctions lambda.
Comprenons l'exemple suivant.
Programme 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)>
Optimisation
Nous pouvons améliorer les performances de l’algorithme de tri par fusion. Commençons par comprendre la différence entre le tri par fusion descendant et ascendant. L'approche ascendante trie les éléments des listes adjacentes de manière itérative, tandis que l'approche descendante divise les listes en deux moitiés.
La liste donnée est [10, 4, 2, 12, 1, 3], au lieu de la décomposer en [10], [4], [2], [12], [1], [3] - nous divisons dans les sous-listes qui peuvent déjà être triées : [10, 4], [2], [1, 12], [3] et sont maintenant prêtes à les trier.
Le tri par fusion est un algorithme inefficace à la fois dans le temps et dans l'espace pour les sous-listes plus petites. Ainsi, le tri par insertion est un algorithme plus efficace que le tri par fusion pour les sous-listes plus petites.
Conclusion
Le tri par fusion est un algorithme populaire et efficace. C'est un algorithme plus efficace pour les grandes listes. Cela ne dépend pas de décisions malheureuses qui conduisent à de mauvais temps d'exécution.
Il y a un inconvénient majeur dans le tri par fusion. Il utilise la mémoire supplémentaire utilisée pour stocker les copies temporaires des listes avant de les fusionner. Cependant, le tri par fusion est largement utilisé dans le logiciel. Ses performances sont rapides et produisent un excellent résultat.
algorithme kmp
Nous avons brièvement discuté du concept de tri par fusion et l'avons implémenté à la fois sur une simple liste d'entiers et sur des objets personnalisés via une fonction lambda utilisée à des fins de comparaison.