如何找出mergesort实现的时间复杂度?

时间:2015-06-01 15:42:27

标签: algorithm big-o time-complexity

我们都知道合并排序算法的时间复杂度是“N Log N”。但是从这下面的代码如何逐步计算这个“N Log N”大O符号?关于这个问题在互联网上有一些答案,但它们很难理解。请帮我理解。百万提前感谢。

#include<stdio.h>
#define MAX 50

void mergeSort(int arr[],int low,int mid,int high);
void partition(int arr[],int low,int high);

int main(){

    int merge[MAX],i,n;

    printf("Enter the total number of elements: ");
    scanf("%d",&n);

    printf("Enter the elements which to be sort: ");
    for(i=0;i<n;i++){
         scanf("%d",&merge[i]);
    }

    partition(merge,0,n-1);

    printf("After merge sorting elements are: ");
    for(i=0;i<n;i++){
         printf("%d ",merge[i]);
    }

   return 0;
}

void partition(int arr[],int low,int high){

    int mid;

    if(low<high){
         mid=(low+high)/2;
         partition(arr,low,mid);
         partition(arr,mid+1,high);
         mergeSort(arr,low,mid,high);
    }
}

void mergeSort(int arr[],int low,int mid,int high){

    int i,m,k,l,temp[MAX];

    l=low;
    i=low;
    m=mid+1;

    while((l<=mid)&&(m<=high)){

         if(arr[l]<=arr[m]){
             temp[i]=arr[l];
             l++;
         }
         else{
             temp[i]=arr[m];
             m++;
         }
         i++;
    }

    if(l>mid){
         for(k=m;k<=high;k++){
             temp[i]=arr[k];
             i++;
         }
    }
    else{
         for(k=l;k<=mid;k++){
             temp[i]=arr[k];
             i++;
         }
    }

    for(k=low;k<=high;k++){
         arr[k]=temp[k];
    }
}

我在这个地址找到了这个源代码:

http://www.cquestions.com/2011/07/merge-sort-program-in-c.html

5 个答案:

答案 0 :(得分:2)

表示为emailField的代码中的函数需要if时间,它在范围mergeSort()内的元素上循环常数次。

表示为O(n)的函数,即实际的排序函数,需要'O(nlogn)时间。它实际上可以表示为:

(low,high)

说明:

每次递归调用分区都是partition()。其中有两个,所以T(n) = 2T(n/2) + C*n //for some constant C 。此外,它会调用T(n/2) 2T(n/2),因此我们为某些常量mergeSort()添加O(n)

通过master theorem case 2,使用:C*n,我们知道该函数位于C

<强> TL;博士
排序算法需要c=log_2(2)=1, k=0时间。

作为旁注,函数的命名确实令人困惑。

Theta(n^c* log(n)^(k+1)) = Theta(nlogn),实际排序算法应命名为O(nlogn),当前partition()函数只是合并两个子数组,因此应将其命名为mergeSort() 。这几乎就是它通常被命名的方式,例如你可以在wikipedia

中看到

答案 1 :(得分:2)

Time Complexity of Merge Sort

如果您知道如何获得合并排序的递归关系,那么对于时间复杂度,上述解释就足够了。

答案 2 :(得分:1)

基本上,从here开始,它正在进行合并(需要O(n)时间)并且执行O(lon n)次 - 因为每次都会将数字数组减半。 / p>

答案 3 :(得分:1)

如果您想要将时间复杂度作为T(n)=等式的等式,则为每行分配值。例如,每个赋值语句都获得1unit(这些语句如 scanf(“%d”,&amp; n); )。循环运行的最大次数是该循环的时间值。例如 {for(i = 0; i小于n; i ++} 此行的值为n,因为它循环通过n次。在添加每个步骤和值之后,你将得到一个形式为T(n)= n +的等式。最高阶项将是整个算法的大O.例如你得到一个T (n)= n ^ 3 + n ^ 2 + 700,这里n ^ 3是最高阶项,所以整个算法的大O是n ^ 3(n立方体)。其余的并不重要T(n)是。

答案 4 :(得分:1)

让我们以Merge Sort的实现为例

 void mergesort(Item a[], int l, int r) {
 if (r <= l) return;
 int m = (r+l)/2;
 mergesort(a, l, m);  ------------ (1)
 mergesort(a, m+1, r); ------------(2)
 merge(a, l, m, r);

a)此合并排序的时间复杂度为O(nlg(n))。并行化(1)和(2)会带来任何实际收益吗?从理论上讲,似乎在并行化后,你最终会得到O(nlg(n)。但实际上我们可以获得任何收益吗?

b)此合并排序的空间复杂度为O(n)。但是,如果我选择使用链接列表执行就地合并排序(不确定是否可以合理地使用数组),空间复杂度将变为O(lg(n)),因为您必须考虑递归堆栈帧大小?我们可以将O(lg(n))视为常数,因为它不能超过64吗?我可能在几个地方误解了这一点。 64的意义究竟是什么?

c)http://www.cprogramming.com/tutorial/computersciencetheory/sortcomp.html表示合并排序需要使用链接列表的常量空间。怎么样 ?他们是否对待O(lg(n)常数?

enter image description here

d)[添加以获得更多清晰度]对于空间复杂度计算,假设输入数组或列表已经在内存中是公平的吗?当我进行复杂度计算时,我总是计算除了已经输入的空间之外我将需要的“额外”空间。否则,空间复杂性将始终为O(n)或更差。

e)列表只需要在合并过程中更改一些指针。这需要不断增加内存。

f)这就是为什么在合并 - 排序复杂性分析中,人们会提到“额外的空间需求”或类似的东西。很明显,你必须将元素存储在某个地方,但最好提一下“额外的记忆”来保持纯粹主义者的存在。