我无法理解合并排序中子数组的大小。在以下代码中:
public void mergeSort(List<Integer> list, int low, int high){
if(low<high){
int mid = (high+low)/2;
mergeSort(list,low, mid);
mergeSort(list,mid+1,high);
merge(list, low, mid, high);
}
}
private void merge(List<Integer> list ,int low, int mid, int high){
int lSize = mid-low+1;
int rSize = high-mid;
//etc
}
对于子数组的大小,我必须在左边添加1,而在右边的数组不添加1。我知道,如果我们有一个大小为10的数组,索引将是0..9和lSize将是4-0 + 1,rSize是9-4。
我不确定该如何措辞,但是我无法绕开要在其中添加+1的位置缠绕头部,而没有在我的头中进行整个大小为10的示例数组。如果我有一阵子不触摸mergesort,则会忘记在+1的位置添加内容。有没有更简单的方法来记住这一点?谢谢。
答案 0 :(得分:0)
这是一个例子。假设清单包含10个元素。这是列表中的索引
0 1 2 3 4 5 6 7 8 9
现在,必须将列表分成两半,然后将每一半递归地排序-一半为0 1 2 3 4,另一半为5 6 7 8 9。因此,上半部分必须在4处停止,而下半部分必须在5处开始并在9处结束。
如果计算中途点mid = (9 + 0) / 2
,则应该为4.5,但是由于这是整数数学,因此会被截断(不舍入,截断)为4。因此,您使用mid
(4)作为上半年的结束,mid + 1
(5)作为下半年的开始。
我希望情况会更清楚
答案 1 :(得分:0)
首先,永远不要添加然后划分索引。如果数组很大,并且您接近数组的结尾,则low
和high
索引如果溢出Integer.MAX_VALUE
,则总和为负数。然后,将其除以2将得到一个负值,而不是您期望的正值。
这里是a Google blog post about the issue。 Java中的更正方法是(请注意,这是>>>
,而不是>>
):
int mid = (high + low) >>> 1;
话虽这么说,这是解决问题的艰难方法,然后是解决问题的简单方法。
问题在于如何处理偶数或奇数low
和偶数或奇数high
值,以使左右两侧的大小始终保持平衡。
让我们创建一个表,其中包含可接受的lSize
和rSize
值,这些值可以适当平衡:
┏━━━━┯━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━┓
┃ low ╲ high ┃ 4 ┃ 5 ┃
┣━━━━━━┷━━━━━╋━━━━━━━━━━━━╇━━━━━━━━━━━━┫
┃ 0 ┃ 2/3 or 3/2 │ 3/3 ┃
┣━━━━━━━━━━━━╉────────────┼────────────┨
┃ 1 ┃ 2/2 │ 2/3 or 3/2 ┃
┗━━━━━━━━━━━━┻━━━━━━━━━━━━┷━━━━━━━━━━━━┛
关联的mid
值为:
┏━━━━┯━━━━━━━┳━━━┳━━━┓
┃ low ╲ high ┃ 4 ┃ 5 ┃
┣━━━━━━┷━━━━━╋━━━╇━━━┫
┃ 0 ┃ 2 │ 2 ┃
┣━━━━━━━━━━━━╉───┼───┨
┃ 1 ┃ 2 │ 3 ┃
┗━━━━━━━━━━━━┻━━━┷━━━┛
因此,我们知道它将类似于mid - low
和high - mid
,但我们可能需要对其进行调整。这些总和是否等于您正在使用的总大小?
┏━━━━┯━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┓
┃ low ╲ high ┃ 4 ┃ 5 ┃
┣━━━━━━┷━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━┫
┃ 0 ┃ (2 - 0) + (4 - 2) = 4 │ (2 - 0) + (5 - 2) = 5 ┃
┣━━━━━━━━━━━━╉───────────────────────┼───────────────────────┨
┃ 1 ┃ (2 - 1) + (4 - 2) = 3 │ (3 - 1) + (5 - 3) = 4 ┃
┗━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━┛
因此,我们比需要的位置少一个,因此我们需要在mid - low
或high - mid
上增加一个,但是哪个?好吧,我们为这两个表制作表格并与我们的第一个表格进行比较。
如果将一个添加到mid - low
会发生什么?
┏━━━━┯━━━━━━━┳━━━━━┳━━━━━┓
┃ low ╲ high ┃ 4 ┃ 5 ┃
┣━━━━━━┷━━━━━╋━━━━━╇━━━━━┫
┃ 0 ┃ 3/2 │ 3/3 ┃
┣━━━━━━━━━━━━╉─────┼─────┨
┃ 1 ┃ 2/2 │ 3/2 ┃
┗━━━━━━━━━━━━┻━━━━━┷━━━━━┛
如您所见,与我们第一个表中可接受的选项匹配。如果将一个添加到high - mid
,会发生什么?
┏━━━━┯━━━━━━━┳━━━━━┳━━━━━┓
┃ low ╲ high ┃ 4 ┃ 5 ┃
┣━━━━━━┷━━━━━╋━━━━━╇━━━━━┫
┃ 0 ┃ 2/3 │ 2/4 ┃
┣━━━━━━━━━━━━╉─────┼─────┨
┃ 1 ┃ 1/3 │ 2/3 ┃
┗━━━━━━━━━━━━┻━━━━━┷━━━━━┛
如您所见,那是不平衡的。
因此,我们有mid - low + 1
和high - mid
。
是否已调试打印lSize
和rSize
值(System.err.printf("L:%d R:%d\n", lSize, rSize);
),并将其添加到lSize
,然后将其添加到rSize
。尝试使用不同的数组大小,看看哪一个平衡左右两侧的效果最佳。