我们都知道合并排序算法的时间复杂度是“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
答案 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)
答案 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)常数?
d)[添加以获得更多清晰度]对于空间复杂度计算,假设输入数组或列表已经在内存中是公平的吗?当我进行复杂度计算时,我总是计算除了已经输入的空间之外我将需要的“额外”空间。否则,空间复杂性将始终为O(n)或更差。
e)列表只需要在合并过程中更改一些指针。这需要不断增加内存。
f)这就是为什么在合并 - 排序复杂性分析中,人们会提到“额外的空间需求”或类似的东西。很明显,你必须将元素存储在某个地方,但最好提一下“额外的记忆”来保持纯粹主义者的存在。