mergesort将序列分成两半

时间:2013-04-27 18:59:03

标签: mergesort

通常,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符号会是什么?

5 个答案:

答案 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更差:)