我正在学习用Java实现一些更简单的算法,但我无法弄清楚为什么这个语句有效:
private void doMergeSort(int lowerIndex, int higherIndex) {
if (lowerIndex < higherIndex) {
int middle = lowerIndex + (higherIndex - lowerIndex) / 2;
doMergeSort(lowerIndex, middle);
doMergeSort(middle + 1, higherIndex);
mergeParts(lowerIndex, middle, higherIndex);
}
}
我经历了调试,我不明白如何调用doMergeSort的第二个实例 - doMergeSort(middle + 1,higherIndex); - 当前一个doMergeSort的最后一次迭代将0,0送入方法时。这不会导致if语句返回false,第二个doMergeSort调用不执行吗?
此代码确实运行,结果是正确的,但这怎么可能?
答案 0 :(得分:1)
我认为您混淆的原因是,您认为lowerIndex
,middle
和higherIndex
的变量会在递归调用中得到修改。他们没有。每个递归调用都会获得它们对这些字段的单独副本,因此对doMergeSort(middle + 1, higherIndex);
的第二次调用不会使用更新的middle
和higherIndex
,它会使用这些值的任何值当他们被传递到doMergeSort(int lowerIndex, int higherIndex)
因此,如果要打印每个调用的变量,它们看起来就像这样......
doMergeSort(0,9)
doMergeSort(0,4)
doMergeSort(0,2)
doMergeSort(0,1)
doMergeSort(0,0)
doMergeSort(1,1)
mergeParts(0,0,1)
doMergeSort(2,2)
mergeParts(0,1,2)
doMergeSort(3,4)
doMergeSort(3,3)
doMergeSort(4,4)
mergeParts(3,3,4)
mergeParts(0,2,4)
doMergeSort(5,9)
doMergeSort(5,7)
doMergeSort(5,6)
doMergeSort(5,5)
doMergeSort(6,6)
mergeParts(5,5,6)
doMergeSort(7,7)
mergeParts(5,6,7)
doMergeSort(8,9)
doMergeSort(8,8)
doMergeSort(9,9)
mergeParts(8,8,9)
mergeParts(5,7,9)
mergeParts(0,4,9)
答案 1 :(得分:0)
0或1项的序列无关:它们已经被订购。
因此,如果函数在这种情况下立即返回,则无关紧要(并且可以说是正确的)。行为也形成the base-case - 当序列无法进一步划分时。
答案 2 :(得分:0)
我认为通过一个例子可能是最好的。
我们假设初始调用是doMergeSort(0,3)[lowerIndex = 0,higherIndex = 3]。
在此调用中,middleIndex将为1 [0 +(3-0)/ 2]
这导致以下呼叫:
doMergeSort(0,1)和doMergeSort(2,3)。
查看doMergeSort(0,1),我们得到以下调用:
doMergeSort(0,0)和doMergeSort(1,1)[lowerIndex = 0,middleIndex = 0,higherIndex = 1]
由于doMergeSort(0,0)[lowerIndex = 0,higherIndex = 0]和doMergeSort(1,1)[lowerIndex = 1,higherIndex = 1],lowerIndex不小于higherIndex,它立即返回。
现在让我们看看doMergeSort(2,3)[与上面类似的逻辑]:
它导致调用doMergeSort(2,2)和doMergeSort(3,3),它们也会立即返回,原因与上面相同[lowerIndex不低于higherIndex]
正如dkatlez指出的那样,我相信你的困惑来自于以后的递归调用中变量lowerIndex和higherIndex被修改的事实。答案 3 :(得分:0)
让我们分析当lowerIndex
低于higherIndex
1时,琐碎案例会发生什么:
doMergeSort(3, 4);
private void doMergeSort(int lowerIndex = 3, int higherIndex = 4) {
if (3 < 4) { // true
int middle = 3 + (4 - 3) / 2; // 3.5 truncated to int -> 3
doMergeSort(3, 3); // when you call method with lowerIndex == higherIndex
// first command is "if (3 < 3)" which is false and no
// code inside "if" is running. Your program exits from
// the method and runs next command
doMergeSort(3 + 1 = 4, 4); // same case as previous command
mergeParts(3, 3, 4);
}
}
所有这一切都是因为两件事:
lowerIndex
和higherIndex
之间的差异在每次迭代中都会降低;
方法doMergeSort
具有允许停止递归的边界条件。