병합 정렬 애니메이션 데모 애니메이션으로 코드를 시각화하세요

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

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

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

归并排序算法-(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 데이터 구조 학습 데이터 구조 샤오자위 왕줘 데이터 구조 학습 데이터 구조 저장 대학 데이터 구조 복습 데이터 구조 마사빙 데이터 구조 기초 제로 데이터 구조와 알고리즘 데이터 구조 입문 대학원 시험 데이터 구조 문제 풀이 설명 데이터 구조 기말 복습 컴퓨터 2급