Поиск по сайту:

Алгоритм сортировки слиянием — реализация на Java, C и Python


Сортировка слиянием — один из самых эффективных алгоритмов сортировки. Он работает по принципу «разделяй и властвуй», основанному на идее разбиения списка на несколько подсписков, пока каждый подсписок не будет состоять из одного элемента, и объединения этих подсписков таким образом, чтобы в результате получился отсортированный список.

Рабочее правило сортировки слиянием

Концепция «Разделяй и властвуй» включает три этапа:

  1. Разделите проблему на несколько подзадач.
  2. Решите подзадачи. Идея состоит в том, чтобы разбить проблему на атомарные подзадачи, где они фактически решаются.
  3. Объедините решения подзадач, чтобы найти решение реальной проблемы.

Итак, рабочее правило сортировки слиянием включает в себя следующие шаги:

  1. Разделите несортированный массив на подмассивы, каждый из которых содержит один элемент.
  2. Возьмите соседние пары двух одноэлементных массивов и объедините их, чтобы сформировать массив из двух элементов.
  3. Повторяйте процесс, пока не будет получен один отсортированный массив.

Массив размера «N» делится на две части размером «N/2» каждой. затем эти массивы далее делятся, пока мы не достигнем одного элемента. Базовым случаем здесь является достижение одного единственного элемента. Когда базовый случай срабатывает, мы начинаем объединять левую и правую части и в конце получаем отсортированный массив. Сортировка слиянием многократно разбивает массив на несколько подмассивов, пока каждый подмассив не будет состоять из одного элемента, и объединяет эти подмассивы таким образом, чтобы получить отсортированный массив.

Алгоритм сортировки слиянием

Массив={70,50,30,10,20,40,60}

Мы многократно разбиваем массив на две части: левую и правую. деление происходит от среднего элемента. Мы делим, пока не достигнем одного элемента, а затем начинаем объединять их, чтобы сформировать отсортированный массив.

Реализации сортировки слиянием

Мы реализуем алгоритм сортировки слиянием на Java, C и Python.

1. 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;
	}

}

ВЫХОД

2. Реализация 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; 
} 

ВЫХОД

3. Реализация 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)

ВЫХОД

Сортировка слиянием по временной и пространственной сложности

1. Космическая сложность

Вспомогательное пространство: O(n) Сортировка на месте: Нет Алгоритм: разделяй и властвуй

2. Временная сложность

Сортировка слиянием является рекурсивным алгоритмом, и временная сложность может быть выражена следующим рекуррентным соотношением. T(n)=2T(n/2) + O(n). Решение приведенной выше рекуррентной задачи равно O(nLogn). Список размера N делится на максимальное количество частей Logn, а объединение всех подсписков в один список занимает время O (N), время выполнения этого алгоритма в наихудшем случае составляет O (nLogn). Сложность времени в наилучшем случае: O(n*log n) Временная сложность в наихудшем случае: O(n*log n) Средняя временная сложность: O(n*log n) Временная сложность MergeSort составляет O(n*Log n) во всех 3 случаях (наихудший , среднее и лучшее), так как сортировка слиянием всегда делит массив на две половины и требует линейного времени для объединения двух половин. Дальнейшие чтения:

  • Сортировка слиянием Страница Википедии
  • Пузырьковая сортировка в Java
  • Сортировка вставками в Java