The specific implementation process of merge sort

Author's homepage: paper jie's blog_CSDN blog - C language, algorithm detailed field blogger

Author of this article: Hello everyone, I am paper jie, thank you for reading this article, welcome to build three companies.

This article is included in the column "Detailed Algorithm Explanation", which is carefully crafted for college students and beginners in programming. The author spent a lot of money (time and energy) to build it, and collected all the basic knowledge of algorithms, hoping to help readers.

Other columns: "System Analysis of C Language", "C Language", "C Language - Grammar"

Content sharing: In this issue, we will give a detailed explanation of the Hill sort among the eight major sorts. Grandpas, please move the small benches and sit down.

    -------- Don't need 998, don't want 98, just one button for three times, you can't lose money if you buy three times, you can't be fooled

foreword

In the last issue, we introduced the improved version of selection sort—heap sort, and analyzed its basic idea, code implementation and algorithm complexity in detail. In this issue, we will explain the last of the eight sorts—merge sort.

What is merge sort

Baidu Encyclopedia says that the merge algorithm is to recursively divide the sequence into short sequences, take the direct sequence with only 1 element or the sequence with only 2 elements as the recursive exit of the short sequence, and then divide all the ordered short sequences according to a certain The rules for sorting as long sequences. Merge sort combines the divide-and-conquer strategy, that is, each record in the initial sequence containing n records is regarded as a subsequence of length 1, and then the n subsequences are merged in pairs to obtain n/2 length 2 (when When it is an odd number, there will be an ordered subsequence of length l); the above steps are repeated until an ordered long sequence of length n is obtained. It should be noted that when comparing and exchanging elements, if two elements are equal in size, there is no need to deliberately exchange positions, so this algorithm will not destroy the stability of the sequence, that is, merge sort is also a stable sorting algorithm.

My own understanding is that merge sort is an effective and stable sorting algorithm based on merge operations. This algorithm is a very typical application of divide and conquer. Combine the ordered subsequences to obtain a completely ordered sequence; that is, first make each subsequence in order, and then make the subsequence segments in order. Merging two sorted lists into one sorted list is called a two-way merge.

Implementation of Merge Sort

basic idea

1 Divide the sequence into two halves with as many elements as possible. 
2 Merge and sort the two halves of the elements separately.
3 Merge two sorted arrays into one.

specific code

#include <stdio.h>
int merge(int r[],int s[],int x1,int x2,int x3)    //自定义实现一次归并样序的函数
{
    int i,j,k;
    i=x1;    //第一部分的开始位置
    j=x2+1;  //第二部分的开始位置
    k=x1;
    while((i<=x2)&&(j<=x3))    //当i和j都在两个要合并的部分中时
        if(r[i]<=r[j])    //筛选两部分中较小的元素放到数组s中
        {
            s[k] = r[i];
            i++;
            k++;
        }
        else
        {
            s[k]=r[j];
            j++;
            k++;
        }
        while(i<=x2)    //将x1〜x2范围内未比较的数顺次加到数组r中
            s[k++]=r[i++];
        while(j<=x3) //将x2+l〜x3范围内未比较的数顺次加到数组r中
            s[k++]=r[j++];
    return 0;
}
int merge_sort(int r[],int s[],int m,int n)
{
    int p;
    int t[20];
    if(m==n)
        s[m]=r[m];
    else
    {
        p=(m+n)/2;
        merge_sort(r,t,m,p);    //递归调用merge_soit()函数将r[m]〜r[p]归并成有序的t[m]〜t[p]
        merge_sort(r,t,p+1,n);    //递归一调用merge_sort()函数将r[p+l]〜r[n]归并成有序的t[p+l]〜t[n]
        merge(t,s,m,p,n);    //调用函数将前两部分归并到s[m]〜s[n】*/
    }
    return 0;
}
int main()
{
    int a[11];
    int i;
    printf("请输入10个数:\n");
    for(i=1;i<=10;i++)
        scanf("%d",&a[i]);    //从键盘中输入10个数
    merge_sort(a,a,1,10);    //调用merge_sort()函数进行归并排序
    printf("排序后的顺序是:\n");
    for(i=1;i<=10;i++)
        printf("%5d",a[i]);    //输出排序后的数据
    printf("\n");
    return 0;
}

The realization principle of merge sort

Recursion: Calling itself Divide and conquer: Divide a large problem that is difficult to solve directly into some smaller identical problems, so that they can be broken down individually and divided and conquered. For example, 10 chopsticks are not easy to fold, and they are divided into 5 and 5, and 5 is not easy to fold, and then divided into 2 and 3, and they are still difficult to fold, and then divided into 1 and 1 (1 and 2). Divide big problems into small problems of the same type like this, and break them down in each. Merge sort implementation idea: split the array from the middle (divided into left and right parts), the left side is divided into two parts from the middle again, and the right side is divided into two parts from the middle again, and continue to be divided in this way until it can no longer be divided. Merge in an orderly manner from the bottom up. Sorting is finally done.

Suppose we want to sort from smallest to largest. The process of merging is mainly to set a pointer at the starting point of the two sequences. Because the two sequences are already ordered separately, we only need to compare the smallest elements in the two sequences each time, add the smaller elements to the temporary array, and then move the pointer backwards until the A sequence of pointers walks through the entire sequence. Then you need to add the remaining values ​​​​of another sequence to the end of the sorted sequence. Finally, assign the element values ​​of the temporary array back to the original array.

One thing to consider here is, when the elements corresponding to the current pointers of the two sequences are equal, which one should be moved? Although any pointer can be moved, we generally move the pointer of the first sequence. Because this can maintain the stability of the sort. That is, keep the same value in the sequence in the same order after sorting.

The difficulty of merge sorting is how to merge. In fact, this is relatively easy to understand, but more code needs to be written, because it is necessary to consider the situation that the sequence is empty and the value of the temporary sequence is stored back to the original sequence. The difficulty of quick sorting is how to divide. I think the difficulty of merging is relatively difficult to understand.

Another point to note is that quicksort divides the process first and then recurses. Merge is first recursive, then merged. It looks like the opposite but is actually due to the fact that some of the two sorting steps do not need to do anything.

the complexity

space complexity

The space complexity of recursive code doesn't add up like the time complexity. Although each merge operation needs to apply for additional memory space, after the merge is completed, the temporarily allocated memory space is released. At any time, the CPU will only have one function executing, and therefore only one temporary memory space in use. The maximum temporary memory space will not exceed the size of n elements, so the space complexity of merge sort is O(n).

time complexity

In the recursive tree of merge sorting, the number of element elements in each layer of the tree is at most n, which means that each layer can perform at most n comparisons, while the recursive tree has at most log2n layers, and together it is nlog2n.


Guess you like

Origin blog.csdn.net/paperjie/article/details/131490191