合并排序算法没有正确合并

时间:2015-02-05 21:03:03

标签: vba pseudocode mergesort

所以,我确实知道合并排序应该做什么,现在我可以对它进行一些可视化。递归拆分直到数组中只剩下一个元素,因为一个元素的数组已经被排序,它减少了每次递归所需的工作量,并且将已经排序的数组附加到另​​一个数组的计算密集程度要小于按正常迭代排序。

我现在有两个主要问题。一,关于分裂(可能是一个简单的,但如果不修复它会抛弃所有东西),当我通过降低分割它们时 - > 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 

1 个答案:

答案 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中写过任何内容。

如果还有任何问题,请随时提出。