合并排序基础案例(递归)解析

时间:2016-10-22 16:03:07

标签: c mergesort

来自Robert Sedgewick和他的书。凯文韦恩算法第4版

在递归中,部分基本案例代码是

if(end <= start)
    {
        return;
    }

但我检查end永远不会低于start索引。当只剩下1个元素时,只会end = start发生。那么为什么<=小于运算符被使用的地方只有一个相等=的条件一直有效?

假设采用了数组a[8,5,3]

现在中间点是第一个指数,所以在分割后

a[8,5] and a[3]
  

divide(a,0,1) and divide(a,2,2), merge(a,0,1,2)   start小于divide(a,0,1)中的end,start=end函数调用中发生divide(a,2,2)

现在mid是第0个索引。

a[8] and a[5] 
  

divide(a,0,0) and divide(a,1,1), merge(a,0,0,1)   这两个函数调用start=end都是正确的。

因此字面上end从未变得小于start,因此end<start永远不会发生。只发生end=start

任何人都可以解释我为什么要使用&lt;合并排序的基本情况下(小于)运算符?

完整递归代码

int divide(int a[], int start, int end)
{
    int mid;

    if(end<=start)
    {
        return;
    }
    else
    {
        mid = (start+end)/2;
        divide(a, start, mid);
        divide(a, mid+1, end);
        merge(a, start, mid, end);
    }
}

2 个答案:

答案 0 :(得分:3)

divide函数从不使用参数调用自身是正确的,因此end < start。因此,if语句也可以是if (end == start)

如果以不正确的方式从另一个代码调用divide函数,可能会发现它,例如

void foo(int a[]) 
{ 
    divide(a, 5, 3);
}

如果您的支票仅为==而不是<=,则会导致无限循环。因此,使用<=似乎更安全。

原始代码也可以重写为:

int divide(int a[], int start, int end)
{
    int mid;

    if(end > start)
    {
        mid = (start+end)/2;
        divide(a, start, mid);
        divide(a, mid+1, end);
        merge(a, start, mid, end);
    }
}

无论如何,它可能对性能无关紧要 - 优化编译器无论如何都会重新安排事情。

  

顺便说一句:请注意,您的函数据说会返回一个int,但您不会这样做。也许你真的希望它是:void divide(.....)

答案 1 :(得分:1)

你可以写下函数除法的递归部分,如下所示

void divide(int a[], int start, int end)
{
    int mid;

    if(start < end)
    {
        mid = (start+end)/2;
        divide(a, start, mid);
        divide(a, mid+1, end);
        merge(a, start, mid, end);
    }
}