Demostración animada de ordenamiento por mezcla Visualiza tu código con animaciones

图码-数据结构可视化动画版

归并排序 被定义为一种 排序算法 ,其工作原理是将数组划分为更小的子数组,对每个子数组进行排序,然后将已排序的子数组合并在一起以形成最终的排序数组。

简单来说,归并排序的过程就是将数组分成两半,对每一半进行排序,然后将已排序的两半合并在一起。 重复这个过程,直到整个数组排序完毕。

归并排序算法-(1)

归并排序算法

归并排序是如何工作的?

归并排序是一种递归算法,它不断地将数组分成两半,直到无法进一步划分为止,即数组只剩下一个元素(只有一个元素的数组总是已排序)。 然后将已排序的子数组合并为一个已排序的数组。

请参阅下图以了解合并排序的工作原理。

插图:

让我们考虑一个数组 arr[] = {38, 27, 43, 10}

  • 最初将数组分成相等的两半:
归并排序:将数组分成两半

归并排序:将数组分成两半

  • 这些子阵列进一步分为两半。 现在它们变成了不能再被分割的单位长度数组,并且单位长度数组总是排序的。
归并排序:将子数组分成两半(这里是单位长度的子数组)

归并排序:将子数组分成两半(这里是单位长度的子数组)

这些排序子数组合并在一起,我们得到更大的排序子数组。

归并排序:将单位长度的子数组合并成已排序的子数组

归并排序:将单位长度的子数组合并成已排序的子数组

这个合并过程一直持续到从较小的子数组构建排序数组为止。

归并排序:将已排序的子数组合并,得到已排序的数组

归并排序:将已排序的子数组合并,得到已排序的数组

 

下图显示了示例数组 {38, 27, 43, 3, 9, 82, 10} 的完整合并排序过程。 

下面是归并排序的代码实现。

C++

// C++ program for Merge Sort
#include <bits/stdc++.h>
using namespace std;
 
// Merges two subarrays of array[].
// First subarray is arr[begin..mid]
// Second subarray is arr[mid+1..end]
void merge(int array[], int const left, int const mid,
           int const right)
{
    int const subArrayOne = mid - left + 1;
    int const subArrayTwo = right - mid;
 
    // Create temp arrays
    auto *leftArray = new int[subArrayOne],
         *rightArray = new int[subArrayTwo];
 
    // Copy data to temp arrays leftArray[] and rightArray[]
    for (auto i = 0; i < subArrayOne; i++)
        leftArray[i] = array[left + i];
    for (auto j = 0; j < subArrayTwo; j++)
        rightArray[j] = array[mid + 1 + j];
 
    auto indexOfSubArrayOne = 0, indexOfSubArrayTwo = 0;
    int indexOfMergedArray = left;
 
    // Merge the temp arrays back into array[left..right]
    while (indexOfSubArrayOne < subArrayOne
           && indexOfSubArrayTwo < subArrayTwo) {
        if (leftArray[indexOfSubArrayOne]
            <= rightArray[indexOfSubArrayTwo]) {
            array[indexOfMergedArray]
                = leftArray[indexOfSubArrayOne];
            indexOfSubArrayOne++;
        }
        else {
            array[indexOfMergedArray]
                = rightArray[indexOfSubArrayTwo];
            indexOfSubArrayTwo++;
        }
        indexOfMergedArray++;
    }
 
    // Copy the remaining elements of
    // left[], if there are any
    while (indexOfSubArrayOne < subArrayOne) {
        array[indexOfMergedArray]
            = leftArray[indexOfSubArrayOne];
        indexOfSubArrayOne++;
        indexOfMergedArray++;
    }
 
    // Copy the remaining elements of
    // right[], if there are any
    while (indexOfSubArrayTwo < subArrayTwo) {
        array[indexOfMergedArray]
            = rightArray[indexOfSubArrayTwo];
        indexOfSubArrayTwo++;
        indexOfMergedArray++;
    }
    delete[] leftArray;
    delete[] rightArray;
}
 
// begin is for left index and end is right index
// of the sub-array of arr to be sorted
void mergeSort(int array[], int const begin, int const end)
{
    if (begin >= end)
        return;
 
    int mid = begin + (end - begin) / 2;
    mergeSort(array, begin, mid);
    mergeSort(array, mid + 1, end);
    merge(array, begin, mid, end);
}
 
// UTILITY FUNCTIONS
// Function to print an array
void printArray(int A[], int size)
{
    for (int i = 0; i < size; i++)
        cout << A[i] << " ";
    cout << endl;
}
 
// Driver code
int main()
{
    int arr[] = { 12, 11, 13, 5, 6, 7 };
    int arr_size = sizeof(arr) / sizeof(arr[0]);
 
    cout << "Given array is \n";
    printArray(arr, arr_size);
 
    mergeSort(arr, 0, arr_size - 1);
 
    cout << "\nSorted array is \n";
    printArray(arr, arr_size);
    return 0;
}
 
// This code is contributed by Mayank Tyagi
// This code was revised by Joshua Estes


            

C

Java

Python3

C#

Javascript

PHP

输出

给定数组是
12 11 13 5 6 7
排序后的数组是
5 6 7 11 12 13

归并排序的复杂度分析:

时间复杂度: O(N log(N)),归并排序是一种递归算法,时间复杂度可以表示为以下递归关系。 

T(n) = 2T(n/2) + θ(n)

上述递归可以使用递归树方法或主方法来解决。 属于主方法的情况II,递推解为θ(Nlog(N))。 在所有 3 种情况(最差、平均和最佳)下,归并排序的时间复杂度均为 θ(Nlog(N)),因为归并排序始终将数组分为两半,并且需要线性时间来合并两半。

辅助空间: O(N),在合并排序中,所有元素都复制到辅助数组中。 所以归并排序需要N个辅助空间。

归并排序的应用:

  • 对大型数据集进行排序: 合并排序特别适合对大型数据集进行排序,因为它保证最坏情况的时间复杂度为 O(n log n)。
  • 外部排序: 归并排序常用于外部排序,当待排序的数据太大而无法放入内存时。
  • 自定义排序: 合并排序可以适应处理不同的输入分布,例如部分排序、接近排序或完全未排序的数据。
  • 倒数计数问题

归并排序的优点:

  • 稳定性 :归并排序是一种稳定的排序算法,这意味着它保持输入数组中相等元素的相对顺序。
  • 保证最坏情况下的性能: 归并排序的最坏情况时间复杂度为 O(N logN),这意味着即使在大型数据集上它也能表现良好。
  • 可并行化 :合并排序是一种天然可并行化的算法,这意味着它可以轻松并行化以利用多个处理器或线程。

归并排序的缺点:

  • 空间复杂度: 归并排序在排序过程中需要额外的内存来存储合并后的子数组。 
  • 非就地: 合并排序不是就地排序算法,这意味着它需要额外的内存来存储排序后的数据。 这对于关注内存使用的应用程序来说可能是一个缺点。
  • 对于小数据集并不总是最佳的: 对于小数据集,合并排序比其他一些排序算法(例如插入排序)具有更高的时间复杂度。 这可能会导致非常小的数据集的性能降低。

快速链接:

  • 关于合并排序的最新文章
  • 排序的编码练习。
  • 归并排序测验

Ya sea que tu objetivo sea aprobar exámenes, avanzar en tu carrera o simplemente por interés puro, este sitio web de visualización de estructuras de datos y algoritmos será un recurso invaluable.

¡Visita este sitio web y comienza tu viaje de aprendizaje!

Estos son comunes: [Descripción en C] Estructuras de datos y algoritmos Implementación en JAVA de estructuras de datos Fundamentos de estructuras de datos y algoritmos (Universidad de Qingdao - Wang Zhuo) Estructuras de datos y algoritmos Estructuras de datos de Wang Dao Implementación en C de estructuras de datos Curso intensivo de estructuras de datos para salvar el examen final Tutorial en video de estructuras de datos en C Yan Weimin de estructuras de datos Hao Bin de estructuras de datos Examen de posgrado en estructuras de datos Algoritmos y fundamentos de estructuras de datos en JAVA Estructuras de datos de Wang Dao 2022 Aprendizaje de estructuras de datos Pequeña tortuga de estructuras de datos Wang Zhuo Aprendizaje de estructuras de datos Estructuras de datos de la Universidad de Zhejiang Repaso de estructuras de datos Soldado Ma de estructuras de datos Tutorial básico de estructuras de datos Estructuras de datos y algoritmos Introducción a estructuras de datos Explicación de ejercicios de estructuras de datos para examen de posgrado Repaso final de estructuras de datos Nivel 2 de informática