通常,mergesort是通过将序列分成两半并递归排序来执行的。 但是也可以通过将序列除以第三个来执行mergesort吗?
mergesort(array, start, last) {
tri_mid = (start+last)/3;
mergesort(array, start, tri_mid);
mergesort(array, tri_mid+1, last);
merge(array, start, last);
}
这会有效吗?
如果确实如此,那么bigO符号会是什么?
答案 0 :(得分:3)
如果包含第三个递归调用并正确编写合并过程,这应该可以正常工作。通过master theorem,复杂性仍为O( n log n )。
答案 1 :(得分:3)
是的,它肯定会工作,但mergesort的优势在于递归的分而治之的方法。如果每次将列表拆分为两半,那么您将获得O(log2(n)),但由于计算复杂性的工作原理,这相当于O(log n)。如果将列表拆分为两个不相等的部分,那么你的大O表达式仍将是O(log n),因为你将列表拆分为每个级别的几个部分,但它可能比将列表拆分为一半要慢,因为算法不会以最优的方式工作,即拆分列表,对每个部分进行排序,以及合并已排序的子列表。作为思考的食物,想象一下如果mergesort只选择第一个项目作为左子列表,而将每个其他项目选为正确的子列表,会发生什么。然后大O表达式将是O(n ^ 2),这与其他更糟糕的算法一样糟糕。当然,如果你想尝试一下你的想法,那就这样做,并计算时间!然后你就会知道什么是更快的。
答案 2 :(得分:3)
好吧,我想出了这个 - >
让我们说我们想要合并不是2个数组,而是 r no数组。
让元素总数 n
在合并时,我们将访问每个数组中的数据元素,然后与其他数组进行比较,以找出要添加到合并数组的最小数据(用于升序排列)。
比较完成并找出最小值的工作将是 O(r)。 并且因为要添加到合并数组的元素总数不是 n ,所以:
Complexity to merge r arrays with total elements n will be O(nr)
将上述结果应用于Mergesort,每次将数组划分为r个较小的数组
因为,每次将数组划分为r个较小的数组,分割和合并的过程将继续进行 log r n 次。
因此,此类Mergesort的复杂性将为 O(nrlog r n)
现在,让我们试着找出一些给定的 n , r 的值将使复杂性最小。为此,函数 F (r)= nrlog r n 必须相对于r进行区分,并且通常会发现 r = e的值( 2.71) 这不是一个整数。此外,该函数在最小点之后开始增加。 因此,复杂度函数最少的 的整数值是 2或3 强> 但是,(2nlog 2 n - 3nlog 3 n)> 0 强>
因此, r所需的值为3
因此,如果 最佳合并 ,则将数组划分为3个较小的然后合并,然后进行合并。
答案 3 :(得分:1)
如果将数组分为三部分,时间复杂度的递归方程将为:T(n)= 3T(n / 3)+ O(n)。使用主定理,时间复杂度将为即使你将数组除以相等的部分,渐近的复杂性也保持不变。原因是,你必须在每次递归中做两件事,即除法和合并.Merging将仍然是O(nlogn)。总是花费O(n)时间。因此,如果您正在考虑最小化时间复杂度,请尝试考虑一种算法,该算法可以在少于O(n)的时间内合并两个排序的数组。
答案 4 :(得分:0)
这里有一个这样的mergesort的例子: - )
void TRIPLE_MERGESORT(vector<double> &A, int k, int l)
{
if(k<l)
{
int one_third = (l-k)/3;
int two_third = 2*(l-k)/3; // k < k+one_third < k+two_third < l
TRIPLE_MERGESORT(A,k,k+one_third);
TRIPLE_MERGESORT(A,k+one_third+1,k+two_third);
TRIPLE_MERGESORT(A,k+two_third+1,l);
MERGE(A,k,k+one_third,k+two_third);
MERGE(A,k,k+two_third,l);
}
}
MERGE合并数组(向量),可以实现为:
void MERGE(vector<double> &A, int p, int q, int r)
{
int i = p;
int j = q+1;
int lenght = r - p + 1;
int k=0;
vector<double> merged;
merged.assign (lenght,0);
while((i<=q)&&(j<=r))
{
if(A[i] <= A[j])
{
merged[k]=A[i];
++i;
}
else
{
merged[k]=A[j];
++j;
}
k++;
}
if(j<=r)
{
while(j<=r)
{
merged[k]=A[j];
++j;
++k;
}
}
if(i<=q)
{
while(i<=q)
{
merged[k]=A[i];
++i;
++k;
}
}
for (i=0;i<lenght;++i)
A[p+i]=merged[i];
}
度过愉快的一天:)
//编辑://
不能说准确(但可能其他人会说它更好,为什么会这样),但分成3部分比普通的mergesort更复杂(需要更多的工作),所以需要更多的时间。我认为它将是O(n ^ 2),但肯定比正常的mergesort更差:)