来自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);
}
}
答案 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);
}
}