Recherche de site Web

Algorithme de tri par fusion - Implémentation en Java, C et Python


Le tri par fusion est l'un des algorithmes de tri les plus efficaces. Il fonctionne sur le principe de la Répartition et Conquête, basé sur l'idée de décomposer une liste en plusieurs sous-listes jusqu'à ce que chaque sous-liste ne contienne qu'un seul élément, puis de fusionner ces sous-listes de manière à obtenir une liste triée.

Règle de fonctionnement du tri par fusion

Le concept de Diviser pour régner comprend trois étapes :

  1. Divisez le problème en plusieurs sous-problèmes.
  2. Résoudre les sous-problèmes. L'idée est de décomposer le problème en sous-problèmes atomiques, où ils sont réellement résolus.
  3. Combinez les solutions des sous-problèmes pour trouver la solution du problème réel.

Ainsi, la règle de fonctionnement du tri par fusion implique les étapes suivantes :

  1. Divisez le tableau non trié en sous-tableaux, chacun contenant un seul élément.
  2. Prenez des paires adjacentes de deux tableaux à un seul élément et fusionnez-les pour former un tableau de 2 éléments.
  3. Répétez le processus jusqu'à ce qu'un seul tableau trié soit obtenu.

Un tableau de taille 'N' est divisé en deux parties de taille 'N/2'. Ensuite, ces tableaux sont encore divisés jusqu'à ce que nous atteignions un seul élément. Le cas de base ici est d'atteindre un unique élément. Lorsque le cas de base est atteint, nous commençons à fusionner la partie gauche et la partie droite pour obtenir un tableau trié à la fin. Le tri par fusion divise de manière répétée un tableau en plusieurs sous-tableaux jusqu'à ce que chaque sous-tableau ne contienne qu'un seul élément, puis fusionne ces sous-tableaux de manière à obtenir un tableau trié.

Flux de l'algorithme de tri par fusion

Tableau={70,50,30,10,20,40,60}

MergeSort

Nous décomposons à plusieurs reprises le tableau en deux parties, la partie gauche et la partie droite. La division se fait à partir de l'élément du milieu. Nous divisons jusqu'à atteindre un seul élément, puis nous commençons à les combiner pour former un tableau trié.

Implémentations du tri par fusion

Nous allons implémenter l'algorithme de tri par fusion en Java, C et Python.

1. Implémentation Java

package com.journaldev.ds;

public class MergeSort {

	public static void main(String[] args) {

		int[] arr = { 70, 50, 30, 10, 20, 40, 60 };

		int[] merged = mergeSort(arr, 0, arr.length - 1);

		for (int val : merged) {
			System.out.print(val + " ");
		}

	}

	public static int[] mergeTwoSortedArrays(int[] one, int[] two) {

		int[] sorted = new int[one.length + two.length];

		int i = 0;
		int j = 0;
		int k = 0;

		while (i < one.length && j < two.length) {

			if (one[i] < two[j]) {
				sorted[k] = one[i];
				k++;
				i++;
			} else {
				sorted[k] = two[j];
				k++;
				j++;
			}
		}

		if (i == one.length) {

			while (j < two.length) {
				sorted[k] = two[j];
				k++;
				j++;
			}
		}

		if (j == two.length) {

			while (i < one.length) {
				sorted[k] = one[i];
				k++;
				i++;
			}
		}

		return sorted;

	}

	public static int[] mergeSort(int[] arr, int lo, int hi) {

		if (lo == hi) {
			int[] br = new int[1];
			br[0] = arr[lo];

			return br;
		}

		int mid = (lo + hi) / 2;

		int[] fh = mergeSort(arr, lo, mid);
		int[] sh = mergeSort(arr, mid + 1, hi);

		int[] merged = mergeTwoSortedArrays(fh, sh);

		return merged;
	}

}

SORTIE

Implémentation de l'algorithme de tri par fusion en Java

2. Mise en œuvre en C

#include <stdio.h>

void merge(int arr[], int l, int m, int r) 
{ 
    int i, j, k; 
    int n1 = m - l + 1; 
    int n2 =  r - m; 
  
    /* create temp arrays */
    int L[n1], R[n2]; 
  
    /* Copy data to temp arrays L[] and R[] */
    for (i = 0; i < n1; i++) 
        L[i] = arr[l + i]; 
    for (j = 0; j < n2; j++) 
        R[j] = arr[m + 1+ j]; 
  
    /* Merge the temp arrays back into arr[l..r]*/
    i = 0; // Initial index of first subarray 
    j = 0; // Initial index of second subarray 
    k = l; // Initial index of merged subarray 
    while (i < n1 && j < n2) 
    { 
        if (L[i] <= R[j]) 
        { 
            arr[k] = L[i]; 
            i++; 
        } 
        else
        { 
            arr[k] = R[j]; 
            j++; 
        } 
        k++; 
    } 
  
    /* Copy the remaining elements of L[], if there 
       are any */
    while (i < n1) 
    { 
        arr[k] = L[i]; 
        i++; 
        k++; 
    } 
  
    /* Copy the remaining elements of R[], if there 
       are any */
    while (j < n2) 
    { 
        arr[k] = R[j]; 
        j++; 
        k++; 
    } 
} 
  
/* l is for left index and r is the right index of the 
   sub-array of arr to be sorted */
void mergeSort(int arr[], int l, int r) 
{ 
    if (l < r) 
    { 
        // Same as (l+r)/2, but avoids overflow for 
        // large l and h 
        int m = l+(r-l)/2; 
  
        // Sort first and second halves 
        mergeSort(arr, l, m); 
        mergeSort(arr, m+1, r); 
  
        merge(arr, l, m, r); 
    } 
} 
  

void printArray(int A[], int size) 
{ 
    int i; 
    for (i=0; i < size; i++) 
        printf("%d ", A[i]); 
    printf("\n"); 
} 
  
/* Driver program to test above functions */
int main() 
{ 
    int arr[] = {70, 50, 30, 10, 20, 40,60}; 
    int arr_size = sizeof(arr)/sizeof(arr[0]); 
  
    printf("Given array is \n"); 
    printArray(arr, arr_size); 
  
    mergeSort(arr, 0, arr_size - 1); 
  
    printf("\nSorted array is \n"); 
    printArray(arr, arr_size); 
    return 0; 
} 

SORTIE

Implémentation en C du tri par fusion

3. Mise en œuvre de Python

def merge_sort(unsorted_array):
    if len(unsorted_array) > 1:
        mid = len(unsorted_array) // 2  # Finding the mid of the array
        left = unsorted_array[:mid]  # Dividing the array elements
        right = unsorted_array[mid:]  # into 2 halves

        merge_sort(left)
        merge_sort(right)

        i = j = k = 0

        #  data to temp arrays L[] and R[]
        while i < len(left) and j < len(right):
            if left[i] < right[j]:
                unsorted_array[k] = left[i]
                i += 1
            else:
                unsorted_array[k] = right[j]
                j += 1
            k += 1

        # Checking if any element was left
        while i < len(left):
            unsorted_array[k] = left[i]
            i += 1
            k += 1

        while j < len(right):
            unsorted_array[k] = right[j]
            j += 1
            k += 1


Code to print the list
def print_list(array1):
    for i in range(len(array1)):
        print(array1[i], end=" ")
    print()


driver code to test the above code
if __name__ == '__main__':
    array = [12, 11, 13, 5, 6, 7]
    print("Given array is", end="\n")
    print_list(array)
    merge_sort(array)
    print("Sorted array is: ", end="\n")
    print_list(array)

SORTIE

Code Python de tri par fusion

Complexité temporelle et spatiale du tri par fusion

1. Complexité spatiale

Espace auxiliaire : O(n) Tri sur place : Pas d'algorithme : Diviser et Conquérir

2. Complexité Temporelle

Le tri par fusion est un algorithme récursif et la complexité temporelle peut être exprimée par la relation de récurrence suivante. T(n)=2T(n/2) + O(n) La solution de la récurrence ci-dessus est O(nLogn). La liste de taille N est divisée en un maximum de Logn parties, et la fusion de toutes les sous-listes en une seule liste prend un temps O(N), le temps d'exécution dans le pire des cas de cet algorithme est O(nLogn) Complexité temporelle dans le meilleur des cas : O(n*log n) Complexité temporelle dans le pire des cas : O(n*log n) Complexité temporelle moyenne : O(n*log n) La complexité temporelle de MergeSort est O(n*Log n) dans les 3 cas (pire, moyenne et meilleur) car le tri par fusion divise toujours le tableau en deux moitiés et prend un temps linéaire pour fusionner deux moitiés. Lectures complémentaires :

  • Page Wikipédia sur le tri par fusion
  • Tri à bulles en Java
  • Tri par insertion en Java