Python:Inplace Merge排序实现问题

时间:2017-12-11 04:23:07

标签: python mergesort

我在python3中实现了inplace合并排序算法。如果输入数组的长度大于1,则Code接受一个输入数组并以递归方式调用它(将split数组作为输入)。之后,它连接两个排序的数组。这是代码

Sub MoveToMonth()
  Dim n As Long
  Dim nLastRow As Long
  Dim nFirstRow As Long
  Dim lastRow As Integer
  Dim i As Long: i = 1
  Dim CellMonth As String

  ActiveSheet.UsedRange

  With Sheets("DATA_IMPORT")
    nFirstRow = .UsedRange.Cells(1).Row
    nLastRow = .UsedRange.Rows(.UsedRange.Rows.Count).Row

    n = nLastRow

    With .Cells(n, "B")
      For n = nLastRow To nFirstRow Step -1
        CellMonth = Format(.Value, "mmmm")
        If CellMonth = "November" Then
          .Cells(n, "B").Cut Worksheets("November").Cells(i, "T")
          i = i + 1
        End If
      Next
    End With

  End With

End Sub

现在,如果代码已经过测试,

def merge_sort(array):

    """
    Input : list of values
    Note :
        It divides input array in two halves, calls itself for the two halves and then merges the two sorted halves.
    Returns : sorted list of values

    """

    def join_sorted_arrays(array1, array2):

        """
        Input : 2 sorted arrays.
        Returns : New sorted array

        """

        new_array = []    # this array will contain values from both input arrays.
        j = 0             # Index to keep track where we have reached in second array
        n2 = len(array2)

        for i, element in enumerate(array1):
            # We will compare current element in array1 to current element in array2, if element in array2 is smaller, append it
            # to new array and look at next element in array2. Keep doing this until either array2 is exhausted or an element of
            # array2 greater than current element of array1 is found.
            while j < n2 and element > array2[j]:
                new_array.append(array2[j])
                j += 1
            new_array.append(element)
        # If there are any remaining values in array2, that are bigger than last element in array1, then append those to 
        # new array.
        for i in range(j,n2):
            new_array.append(array2[i])
        return new_array

    n = len(array)
    if n == 1:
        return array
    else:
        # print('array1 = {0}, array2 = {1}'.format(array[:int(n/2)], array[int(n/2):]))
        array[:int(n/2)] = merge_sort(array[:int(n/2)])
        array[int(n/2):] = merge_sort(array[int(n/2):])
        # print('array before joining : ',array)
        array = join_sorted_arrays(array[:int(n/2)],array[int(n/2):])
        # print('array after joining : ',array)
        return array

如果在上面的函数中取消注释print语句,你会注意到a =给定的输出,就在最后一次调用join_sorted_arrays之前。调用此函数后,应对数组'a'进行排序。令我惊讶的是,如果我执行以下操作,输出是正确的。

 a = [2,1,4,3,1,2,3,4,2,7,8,10,3,4]
 merge_sort(a)
 print(a)
 out : [1, 1, 2, 2, 3, 3, 4, 2, 3, 4, 4, 7, 8, 10]

我需要一些帮助来理解为什么会这样。 我是初学者,所以关于编码实践等的任何其他评论也是受欢迎的。

1 个答案:

答案 0 :(得分:1)

当您使用

重新指定array作为join_sorted_arrays()的输出时
array = join_sorted_arrays(array[:int(n/2)],array[int(n/2):])

您不再更新a的值。

当您将a作为参数array传递时,可以理解为什么函数中名为array的所有变量看起来都应该更新原始值array(又名a)。但相反,array = join_sorted_arrays(...)发生的事情是您在array函数中有一个新变量merge_sort()。从函数返回array将返回新的,已排序的值集。

a的引用在最后一个语句之前被修改,这就是为什么它在print(a)之后与merge_sort(a看起来不同的原因。但是,您只能从merge_sort()的返回值中获取最终的排序输出。

如果你看一下可能会更清楚:

b = merge_sort(a)
print(a) # [1, 1, 2, 2, 3, 3, 4, 2, 3, 4, 4, 7, 8, 10]
print(b) # [1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 7, 8, 10]

请注意,Python并不是一种传递引用语言,而实际上它的实际细节可能有点奇怪。当我被绊倒时,我总是回去看看它是如何工作的。关于这个话题有很多SO帖子,这可能对你有用。
例如,this onethis one