merge sort

Merge sorting also adopts the idea of ​​​​divide and conquer, which uses the dichotomy method to divide the array to be sorted into several sub-arrays. Then merge adjacent sub-arrays into a new ordered sub-array, and then merge into a new ordered array based on the new sub-array until they are merged into an overall ordered array.

Algorithm idea
The most basic idea of ​​merge sort is to split an array into two arrays, then sort each sub-array, and then merge the two ordered sub-arrays into one ordered array.

The merge sort algorithm can be roughly divided into two steps, as shown in the figure below:
Insert image description here

Decomposition (Split)
If the length of the array is 1, the array is considered to be in order and can be returned directly.
If the array length is greater than 1, decompose the array into two sub-arrays from the middle, and then decompose each sub-array until the length of each sub-array is 1.
Merge
sorts and merges each adjacent sub-array until all sub-arrays are sorted and merged.
The final merged array is the sorted ordered array.
Below we focus on the process of sorting and merging and code implementation ideas:

Taking the array A{2, 3, 1, 4} as an example, first copy A and store it in B. Since the left and right indexes of B are l=0 and r=3 respectively, its mid = (l+r)/2 , since l and r are both int types, so mid=1; according to the decomposition method in the merge sort algorithm, we will {2, 3} (corresponding to the interval [l, mid] in B) and {1, 4} (corresponding to the interval [mid+1, r] in B) as the two sub-arrays split from A (and they are already in order and can be sorted and merged directly). Use indexes i and j to point to the first elements of the two sub-arrays respectively, and index k to point to the first element of the original array A.

Insert image description here

Compare the sizes of B[i] and B[j]. At this time, 2>1, so the value 1 of B[j] is assigned to A[k], and then j and k are moved back one bit. The result is shown below:

Insert image description here

Then compare the sizes of B[i] and B[j] again. At this time, 2<4, so the value 2 of B[i] is assigned to A[k], and then both i and k are moved back one bit. The result is shown below:

Insert image description here

Next, continue to compare the sizes of B[i] and B[j]. At this time, 3<4, so the value 3 of B[i] is assigned to A[k], and then both i and k are moved back one bit. The result is shown below:

Insert image description here

At this time i>mid, that is, the sub-arrays {2, 3} have all been merged into A, and there is only one element 4 left in the sub-arrays {1, 4}. The value 4 of B[j] is assigned to A[k], and then i and k are both moved back one position, and the merge is completed at this time. As shown below:

Insert image description here

Code

#include <algorithm>
#include <iostream>

// 将arr[l,mid]和arr[mid+1,r]的数组进行归并
template <typename T>
void merge_(T arr[], int l, int mid, int r) {
    
    
    T *tmp = new T[r - l + 1];
    for (int i = l; i <= r; ++i)
        tmp[i - l] = arr[i];  // tmp从0开始,对应的arr有l个偏移

    int i = l, j = mid + 1;
    for (int k = l; k <= r; ++k) {
    
    
        if (i > mid)  // 如果左半部分元素已经全部处理完毕
        {
    
    
            arr[k] = tmp[j - l];
            j++;
        } else if (j > r)  // 如果右半部分元素已经全部处理完毕
        {
    
    
            arr[k] = tmp[i - l];
            i++;
        } else if (tmp[i - l] < tmp[j - l])  // i所指元素(对应的是tmp[i-l]) <
            // j所指元素(对应的是tmp[j-l])
        {
    
    
            arr[k] = tmp[i - l];
            i++;
        } else  // i所指元素(对应的是tmp[i-l]) >= j所指元素(对应的是tmp[j-l])
        {
    
    
            arr[k] = tmp[j - l];
            j++;
        }
    }
    delete[] tmp;
}

// 递归使用归并排序,对arr[l...r]的范围进行排序
template <typename T>
void mergeSort_(T arr[], int l, int r) {
    
    
    if (l >= r) return;

    int mid = (l + r) / 2;
    mergeSort_(arr, l, mid);
    mergeSort_(arr, mid + 1, r);
    merge_(arr, l, mid, r);
}

template <typename T>
void mergeSort(T arr[], int n) {
    
    
    mergeSort_(arr, 0, n - 1);
}

int main() {
    
    
    int arr[] = {
    
    3, 5, 2, 1, 4};
    mergeSort(arr, 5);
    for (int i = 0; i < 5; ++i) {
    
    
        std::cout << arr[i] << " ";
    }
    std::cout << std::endl;
    return 0;
}

Complexity
Space complexity: During the merging process, a space of the same size as the array to be sorted needs to be opened, so the space complexity is O(n).
Time complexity: Due to the decomposition and merging of arrays, the complexity of decomposition and merging is O(logn), and each merging requires a comparison operation, and the corresponding complex pair is O(n), so The time complexity of merge sort is O(nlogn).

Guess you like

Origin blog.csdn.net/weixin_40933653/article/details/133376910