Detailed explanation and examples of merge sort algorithm

merge sort

The merge sort algorithm is a sorting algorithm designed on the basis of the divide and conquer algorithm. It can complete the ascending order (from small to large) or descending order (from large to small) of the specified sequence, and the time complexity is O ( nlogn ) O(nlogn)O(nlogn)

The idea of ​​​​realizing sorting

1. Divide the entire sequence to be sorted into multiple non-dividable sequences to be sorted, and each subsequence has only one element; 2.
Merge all subsequences in pairs, complete the sorting operation during the merging process, and finally merge to obtain a new A sequence is a sorted sequence.

example

Use the merge sort algorithm to {7, 6, 8, 9, 3, 4, 1, 0} to realize the process of sorting in ascending order.
1. Divide {7, 6, 8, 9, 3, 4, 1, 0} into multiple subsequences, each subsequence contains only one element, the division process is as follows:
insert image description here
Figure 1 Merge sort algorithm segmentation process
2. Merge the final split sequences in pairs and reintegrate them into an ordered sequence. The merging process is as follows:
insert image description here
Figure 2 The process of integrating all subsequences by the merge sorting algorithm.

pseudocode

The merge sort algorithm can be implemented with the help of recursion:

对应的伪代码如下:
输入arr[n]   //输入要排序的序列
merge_sort(arr[n], p, q){
    
     //对[p,q]区域大的元素进行归并排序
	if p < q;             //对[p,q]区域不断采用对半分割的方式,最终将整个区域划分为多个仅包含1个元素(p==q)的序列
	mid = (p+q)/2;
	merge_sort(arr[n],p,mid);
	merge_sort(arr[n],mid+1,q);
	merge(arr,p,mid,q);            //调用实现归并过程的代码模块。
}
merge_sort() 用于将整个序列分割成多个子序列,merge() 用来合并这些子序列,合并的实现方式为:
1.[p, mid][mid+1, q] 两个区域的元素分别拷贝到 leftarr 和 rightarr 区域。
2.从 leftarr 和 rightarr 区域中各个取出第一个元素,比较它们的大小;
3.将较小的元素拷贝到 [p, q] 区域,然后从较小元素所在的区域内取出下一个元素,继续进行比较;
4.重复执行第 3 步,直至 leftarr 和 rightarr 内的元素全部拷贝到 [p, q] 为止。
  如果 leftarr 或者 rightarr 有一方为空,则直接将另一方的所有元素依次拷贝到 [p, q] 区域。
对应的伪代码如下:
merge(arr[n] , p , mid , q):                          // 该算法表示将 [p , mid] 和 [mid+1 , q] 做归并操作
    leftnum <- mid - p + 1                            // 统计 [p , mid] 区域内的元素个数
    rightnum <- q - mid                               // 统计 [mid+1 , q] 区域内的元素个数
    leftarr[leftnum] <- arr[p ... mid]                // 分别将两个区域内的元素各自拷贝到另外两个数组中
    rightarr[rightnum] <- arr[mid+1 ... q]
    i <- 1 , j <- 1
    for k <- p to q :             // 从 leftarr 和 rightarr 数组中第 1 个元素开始,比较它们的大小,将较小的元素拷贝到 arr 数组的 [p , q] 区域
        if leftarr[i] ≤ rightarr[j] :
            arr[k] = leftarr[i]
            i <- i+1
        else :
            arr[k] = right[j]
            j <- j+1

Combined with the pseudocode, the following is a C language program that uses the merge sort algorithm to sort {7,6,8,9,3,4,1,0} in ascending order:

#include <stdio.h>
//实现分割操作的函数
void merge_sort(int* arr, int p, int q);
//实现归并操作的函数
void merge(int* arr, int p, int mid, int q);
int main() {
    
    
    int i = 0;
    int arr[8] = {
    
     7,6,8,9,3,4,1,0 };
    //对 arr 数组中第 1 至 8 个元素进行归并排序
    merge_sort(arr, 1, 8);
    while (i < 8)
    {
    
    
        printf("%d ", arr[i]);
        i++;
    }
    return 0;
}
//实现分割操作的函数,[p,q] 用于指定归并排序的区域范围,
void merge_sort(int* arr, int p, int q) {
    
    
    int mid;
    if (arr == NULL || p > q || p == q) {
    
    
        return ;
    }
    mid = (p + q) / 2;
    //将 [p,q] 分为[p,mid] 和 [mid+1,q] 区域
    merge_sort(arr, p, mid);
    merge_sort(arr, mid + 1, q);
    //对分好的 [p,mid] 和 [mid,q] 进行归并操作
    merge(arr, p, mid, q);
}
//实现归并操作的函数,归并的 2 个区域分别为 [p,mid] 和 [mid+1,q]
void merge(int* arr, int p, int mid, int q) {
    
    
    int i,j,k;
    int leftarr[100], rightarr[100];
    int numL = mid - p + 1;
    int numR = q - mid;
    //将 arr 数组中 [p,mid] 区域内的元素逐一拷贝到 leftarr 数组中
    for (i = 0; i < numL; i++) {
    
    
        leftarr[i] = arr[p - 1 + i];
    }
    //将 arr 数组中 [mid+1,q] 区域内的元素逐一拷贝到 rightarr 数组中
    leftarr[i] = 2147483647;
    for (i = 0; i < numR; i++) {
    
    
        rightarr[i] = arr[mid + i];
    }
    rightarr[i] = 2147483647;
    i = 0;
    j = 0;
    //逐一比较 leftarr 和 rightarr 中的元素,每次将较小的元素拷贝到 arr 数组中的 [p,q] 区域内
    for (k = p; k <= q; k++) {
    
    
        if (leftarr[i] <= rightarr[j]) {
    
    
            arr[k - 1] = leftarr[i];
            i++;
        }
        else {
    
    
            arr[k - 1] = rightarr[j];
            j++;
        }
    }
}

Guess you like

Origin blog.csdn.net/qq_43679351/article/details/124942176