所以,我确实知道合并排序应该做什么,现在我可以对它进行一些可视化。递归拆分直到数组中只剩下一个元素,因为一个元素的数组已经被排序,它减少了每次递归所需的工作量,并且将已经排序的数组附加到另一个数组的计算密集程度要小于按正常迭代排序。
我现在有两个主要问题。一,关于分裂(可能是一个简单的,但如果不修复它会抛弃所有东西),当我通过降低分割它们时 - > mid(+/- 1)和mid - >高,我遇到一个问题,基本情况没有正确测试,并提前返回,导致一个未排序的数组。举个例子,我引用另一个论坛的回复,"如果我有5的中间,9的低和0的低,那么我必须从0到5分开,从6分离从9到9,或从0到4,从左到5到9.我遇到的问题是,如果你再次拆分,比如从6到9,由于四舍五入,我有7个中间,这意味着权利将会只有6到7,这使得它失败了hi - low> 2,因为7 - 6等于1且小于2,留下2个可能未分类的元素。"
现在,无论哪种方式都会发生这种情况,因为将+/-添加到mid可能会产生一种奇数低的数字,但这种数字并不好用。我该如何解决这个问题?
其次,在合并时,如何正确(和有效)检查B' sand C的数组边界是否合适。我是否需要另一个条件语句来检查PosB和PosC是否在边界内,如果不是,我怎样才能恰当地(和整齐地)添加另一个数组左边的最终数组。
提前致谢。这应该是在visual basic中,但是现在伪代码似乎是解决这些问题的最好方法,而不是强调正确的语法。
A[] = { 28, 39, 48, 27, 9, 88, 11, 4, 7} ' Global variable, disregard bad programming practices
Function Split(int low, int hi){ ' Adding brackets because not only am I used to java, it should help readability
if (hi - low) < 2 then
return array of elements from [low, hi]
end if
mid = (hi + low) / 2
B[] = split(low, mid-1) ' Either I do mid-1 or mid+1, the results seem the same
C[] = split(mid, hi) ' Same problems as above
D[] = Merge(B[], C[])
return D[]
End Function
Function Merge(B[], C[]) ' I use two arrays because I figured it'd be the easiest to work with.
int PosB = 0, PosC = 0, PosMax = (b.length + c.length) -1 ' PosB and PosC keep track of the positions in the cells of B and C respectively.
'PosMax keeps track of the max cell that E[] (declared below) should have as well as the max number for the for loop
E[num] ' Declare and iniatialize an array that is supposed to hold the combined values of B and C, sorted.
for i = 0 to num
if PosC >= c.length or B[PosB] < C[PosC] ' Checks if C[] already has added everything it has to E[] and if so, proceeds to add the
' supposedly already sorted array B[]'s elements to E[]. Emphasis on "supposedly". A problem here is it does not check for if PosB
' is out of bounds, which is a huge problem with primitive arrays. Also checks if the current element in C is greater than the
' current element in B, and if so, add the element in B and increment.
E[i] = B[PosB]
PosB += 1 ' Does not check whether or not PosB is at the end, gotta figure a way to check
Else
E[i] = C[PosC]
PosC += 1
End If
Next
End Function
答案 0 :(得分:0)
问题是,数组的边界是包容性的,这意味着:
当您从6-8访问位置时,结果中有3个元素(6,7,8)。逻辑结果是:如果你只想要一个数组中的范围描述的一个元素,你将不得不写[6-6]; [6-7]表示仍然有两个元素(6和7)。让我们看一下以下代码:
if (hi - low) < 2 then
return array of elements from [low, hi]
当您将6-7的范围赋予此功能时会发生什么? 7-6 = 1 - &gt;是的 - &gt;返回。但在6-7的范围内仍然是两个要素。因此,要解决此问题,只需撰写(hi - low) < 1
或更容易阅读(hi - low) == 0
即可。
下一点更多的是关于VBA,所以这只是一个想法,因为我对VBA不是很熟悉:
mid = (hi + low) / 2
如果返回一个整数,结果可能会舍入到较低的值((3 + 4)/ 2 = 3)。如果是这样,我会写如下:
B[] = split(low, mid)
C[] = split(mid + 1, hi)
原因是mid
已经是下边界(由于四舍五入)。当边界接近0时,减法1可能会导致一些问题,因为它可能导致负值。
第二部分:
将过程分成两部分会更容易:
E[num]' I don't know what num means but I suppose it's correct here
int PosE = 0
'adding elements to the new array while they can be compared to each other
while(c.length > 0 and b.length > 0)
if(C[PosC] < B[PosB])
E[PosE] = C[PosC]
PosC += 1
Else
E[PosE] = B[PosB]
PosB += 1
End If
PosE += 1
Next
'one of the array B or C (or both) is empty now. The remaining elements have to be added. The order doesn't matter any more.
for i = PosC to c.length 'I don't know if this is possible in VBA but I think you know what I mean: adding all the remaining elements of C to E (if there are any)
E[PosE] = C[PosC]
PosC += 1
PosE += 1
Next
'doing the same with B; it could happen that one of those loops never run
for i = PosB to b.length
E[PosE] = B[PosB]
PosB += 1
PosE += 1
Next
我希望这有效,因为我从未在VB中写过任何内容。
如果还有任何问题,请随时提出。