c语言合并排序算法_合并排序算法

c语言合并排序算法

Merge Sort follows the rule of Divide and Conquer to sort a given set of numbers/elements, recursively, hence consuming less time.

合并排序遵循分而治之的规则,以递归方式对一组给定的数字/元素进行排序,从而减少了时间。

In the last two tutorials, we learned about Selection Sort and Insertion Sort, both of which have a worst-case running time of O(n2). As the size of input grows, insertion and selection sort can take a long time to run.

在最后的两个教程中,我们了解了选择排序和插入排序,这两个类的最坏运行时间均为O(n 2 ) 。 随着输入大小的增长,插入和选择排序可能需要很长时间才能运行。

Merge sort , on the other hand, runs in O(n*log n) time in all the cases.

另一方面,合并排序在所有情况下均以O(n*log n)时间运行。

Before jumping on to, how merge sort works and it's implementation, first lets understand what is the rule of Divide and Conquer?

在继续之前,合并排序如何工作及其实现,首先让我们了解分而治之的规则是什么?

分而治之 (Divide and Conquer)

If we can break a single big problem into smaller sub-problems, solve the smaller sub-problems and combine their solutions to find the solution for the original big problem, it becomes easier to solve the whole problem.

如果我们可以将一个大问题分解为较小的子问题,解决较小的子问题,然后将它们的解决方案结合起来以找到原始大问题的解决方案,那么解决整个问题就变得更加容易。

Let's take an example, Divide and Rule.

让我们以Divide and Rule为例。

When Britishers came to India, they saw a country with different religions living in harmony, hard working but naive citizens, unity in diversity, and found it difficult to establish their empire. So, they adopted the policy of Divide and Rule. Where the population of India was collectively a one big problem for them, they divided the problem into smaller problems, by instigating rivalries between local kings, making them stand against each other, and this worked very well for them.

当英国人来到印度时,他们看到一个宗教信仰不同的国家和睦相处,工作勤奋但天真的公民,多元而团结,发现很难建立自己的帝国。 因此,他们采取了分而治之的政策。 在印度人口集体对他们来说是一个大问题的地方,他们通过煽动地方国王之间的对抗,使他们相互对抗,将问题分为较小的问题,这对他们来说非常有效。

Well that was history, and a socio-political policy (Divide and Rule), but the idea here is, if we can somehow divide a problem into smaller sub-problems, it becomes easier to eventually solve the whole problem.

那是历史,是一项社会政治政策(“ 分而治之” ),但是这里的想法是,如果我们能够以某种方式将一个问题分解为较小的子问题,则最终解决整个问题变得更加容易。

In Merge Sort, the given unsorted array with n elements, is divided into n subarrays, each having one element, because a single element is always sorted in itself. Then, it repeatedly merges these subarrays, to produce new sorted subarrays, and in the end, one complete sorted array is produced.

Merge Sort中 ,给定的具有n元素的未排序数组被划分为n个子数组,每个子数组都有一个元素,因为单个元素始终在自身中进行排序。 然后,它反复合并这些子数组,以生成新的排序后的子数组,最后生成一个完整的排序后的数组。

The concept of Divide and Conquer involves three steps:

分而治之的概念涉及三个步骤:

  1. Divide the problem into multiple small problems.

    鸿沟的问题分成多个小的问题。

  2. Conquer the subproblems by solving them. The idea is to break down the problem into atomic subproblems, where they are actually solved.

    通过解决他们征服的子问题。 想法是将问题分解为原子子问题,并在其中实际解决。

  3. Combine the solutions of the subproblems to find the solution of the actual problem.

    结合子问题的解决方案以找到实际问题的解决方案。

Divide and Conquer algorithm

合并排序如何工作? (How Merge Sort Works?)

As we have already discussed that merge sort utilizes divide-and-conquer rule to break the problem into sub-problems, the problem in this case being, sorting a given array.

正如我们已经讨论的那样,合并排序利用分而治之的规则将问题分解为子问题,在这种情况下,问题是对给定数组进行排序

In merge sort, we break the given array midway, for example if the original array had 6 elements, then merge sort will break it down into two subarrays with 3 elements each.

在归并排序中,我们将给定的数组中途中断,例如,如果原始数组有6元素,则归并排序会将其分解为两个每个具有3元素的子数组。

But breaking the orignal array into 2 smaller subarrays is not helping us in sorting the array.

但是将原始数组分成2个较小的子数组并不能帮助我们对数组进行排序。

So we will break these subarrays into even smaller subarrays, until we have multiple subarrays with single element in them. Now, the idea here is that an array with a single element is already sorted, so once we break the original array into subarrays which has only a single element, we have successfully broken down our problem into base problems.

因此,我们将把这些子数组分解为更小的子数组 ,直到我们拥有多个包含单个元素的数组 。 现在,这里的想法是已经对具有单个元素的数组进行了排序,因此一旦将原始数组分解为仅具有单个元素的子数组,我们就可以成功地将问题分解为基本问题。

And then we have to merge all these sorted subarrays, step by step to form one single sorted array.

然后,我们必须逐步合并所有这些排序后的子数组,以形成一个单独的排序后的数组。

Let's consider an array with values {14, 7, 3, 12, 9, 11, 6, 12}

让我们考虑一个值{14, 7, 3, 12, 9, 11, 6, 12} 14,7,3,12,9,9,11,6,12 {14, 7, 3, 12, 9, 11, 6, 12}的数组

Below, we have a pictorial representation of how merge sort will sort the given array.

下面,我们以图形方式表示合并排序将如何对给定数组进行排序。

Working of Merge Sort algorithm

In merge sort we follow the following steps:

在合并排序中,我们遵循以下步骤:

  1. We take a variable p and store the starting index of our array in this. And we take another variable r and store the last index of array in it.

    我们采用变量p并在其中存储数组的起始索引。 然后,我们使用另一个变量r并将数组的最后一个索引存储在其中。

  2. Then we find the middle of the array using the formula (p + r)/2 and mark the middle index as q, and break the array into two subarrays, from p to q and from q + 1 to r index.

    然后,我们使用公式(p + r)/2找到数组的中间,并将中间索引标记为q ,然后将该数组分为两个子数组,从pq和从q + 1r索引。

  3. Then we divide these 2 subarrays again, just like we divided our main array and this continues.

    然后,我们再次划分这2个子数组,就像划分主数组一样,这种情况将继续。

  4. Once we have divided the main array into subarrays with single elements, then we start merging the subarrays.

    一旦将主数组划分为具有单个元素的子数组,我们便开始合并子数组。

实现合并排序算法 (Implementing Merge Sort Algorithm)

Below we have a C program implementing merge sort algorithm.

下面我们有一个实现合并排序算法的C程序。

/*  
    a[] is the array, p is starting index, that is 0, 
    and r is the last index of array. 
*/

#include <stdio.h>

// lets take a[5] = {32, 45, 67, 2, 7} as the array to be sorted.

// merge sort function
void mergeSort(int a[], int p, int r)
{
    int q;
    if(p < r)
    {
        q = (p + r) / 2;
        mergeSort(a, p, q);
        mergeSort(a, q+1, r);
        merge(a, p, q, r);
    }
}

// function to merge the subarrays
void merge(int a[], int p, int q, int r)
{
    int b[5];   //same size of a[]
    int i, j, k;
    k = 0;
    i = p;
    j = q + 1;
    while(i <= q && j <= r)
    {
        if(a[i] < a[j])
        {
            b[k++] = a[i++];    // same as b[k]=a[i]; k++; i++;
        }
        else
        {
            b[k++] = a[j++];
        }
    }
  
    while(i <= q)
    {
        b[k++] = a[i++];
    }
  
    while(j <= r)
    {
        b[k++] = a[j++];
    }
  
    for(i=r; i >= p; i--)
    {
        a[i] = b[--k];  // copying back the sorted list to a[]
    } 
}

// function to print the array
void printArray(int a[], int size)
{
    int i;
    for (i=0; i < size; i++)
    {
        printf("%d ", a[i]);
    }
    printf("\n");
}
 
int main()
{
    int arr[] = {32, 45, 67, 2, 7};
    int len = sizeof(arr)/sizeof(arr[0]);
 
    printf("Given array: \n");
    printArray(arr, len);
    
    // calling merge sort
    mergeSort(arr, 0, len - 1);
 
    printf("\nSorted array: \n");
    printArray(arr, len);
    return 0;
}

Given array: 32 45 67 2 7 Sorted array: 2 7 32 45 67

给定数组:32 45 67 2 7排序数组:2 7 32 45 67

合并排序的复杂度分析 (Complexity Analysis of Merge Sort)

Merge Sort is quite fast, and has a time complexity of O(n*log n). It is also a stable sort, which means the "equal" elements are ordered in the same order in the sorted list.

合并排序非常快,并且时间复杂度为O(n*log n) 。 这也是一种稳定的排序方式,这意味着“相等”元素在排序列表中的排序顺序相同。

In this section we will understand why the running time for merge sort is O(n*log n).

在本节中,我们将理解为什么合并排序的运行时间为O(n*log n)

As we have already learned in Binary Search that whenever we divide a number into half in every stpe, it can be represented using a logarithmic function, which is log n and the number of steps can be represented by log n + 1(at most)

正如我们在二元搜索中所学到的,每当我们在每个stpe中将数字分为一半时,就可以使用对数函数来表示,即log n ,步数可以由log n + 1表示(最多)

Also, we perform a single step operation to find out the middle of any subarray, i.e. O(1).

同样,我们执行一步操作来找出任何子数组的中间,即O(1)

And to merge the subarrays, made by dividing the original array of n elements, a running time of O(n) will be required.

为了合并通过划分n元素的原始数组而形成的子数组,将需要O(n)的运行时间。

Hence the total time for mergeSort function will become n(log n + 1), which gives us a time complexity of O(n*log n).

因此, mergeSort函数的总时间将变为n(log n + 1) ,这使我们的时间复杂度为O(n*log n)

Worst Case Time Complexity [ Big-O ]: O(n*log n)

最坏情况下的时间复杂度[Big-O]: O(n * log n)

Best Case Time Complexity [Big-omega]: O(n*log n)

最佳情况下的时间复杂度[Big-Omega]: O(n * log n)

Average Time Complexity [Big-theta]: O(n*log n)

平均时间复杂度[Big-theta]: O(n * log n)

Space Complexity: O(n)

空间复杂度: O(n)

  • Time complexity of Merge Sort is O(n*Log n) in all the 3 cases (worst, average and best) as merge sort always divides the array in two halves and takes linear time to merge two halves.

    在所有3种情况下(最差,平均和最佳),合并排序的时间复杂度均为O(n*Log n) ,因为合并排序始终数组分为两半,并花费线性时间来合并两半。

  • It requires equal amount of additional space as the unsorted array. Hence its not at all recommended for searching large unsorted arrays.

    它需要与未排序数组相等数量的额外空间 。 因此,完全不建议搜索大型未排序的数组。

  • It is the best Sorting technique used for sorting Linked Lists.

    这是用于对链表进行排序的最佳排序技术。

翻译自: https://www.studytonight.com/data-structures/merge-sort

c语言合并排序算法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值