正在载入交互式动画窗口请稍等

归并排序 可视化交互式动画版

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

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

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

归并排序算法-(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),这意味着即使在大型数据集上它也能表现良好。
  • 可并行化 :合并排序是一种天然可并行化的算法,这意味着它可以轻松并行化以利用多个处理器或线程。

归并排序的缺点:

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

快速链接:

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

无论你的目标是考试成功、职业发展,还是纯粹的兴趣,这个数据结构和算法可视化的网站都会是一个无价的资源。

前往这个网站,开始你的学习之旅吧!

这些是常见的:【C语言描述】《数据结构和算法》数据结构JAVA实现 数据结构与算法基础(青岛大学-王卓)数据结构与算法王道数据结构c语言实现 速成数据结构期末考前救急 数据结构视频C语言版教程 数据结构严蔚敏 数据结构郝斌 数据结构考研 JAVA数据结构算法与基础 数据结构王道 2022数据结构学习 数据结构小甲鱼 王卓 学习数据结构 数据结构浙江大学 数据结构复习 数据结构马士兵 数据结构零基础教程 数据结构和算法 数据结构入门 考研数据结构习题讲解 数据结构期末复习 计算机二级