mergesort递归版本背后的直觉



我在一本书中发现了mergesort程序的以下部分:

def sort(v):
if len(v)<=1:
return v
mid=len(v)//2
v1,v2=sort(v[:mid]),sort(v[mid:])
return merge(v1,v2)

merge的部分是比较v1和v2的每个元素,并在必要时在它们之间进行交换。我的问题与sort((函数有关。例如,如果我传递一个列表,如:[5,2,4,8,6,3]。它会被分成块,递归地调用sort((函数,但我不知道它在哪一点调用merge((函数。那么,如果我假设下半部分执行的调用集是这样的:

sort([5,4,2])=v1        sort([8,6,3])=v2
(at this point is called merge(v1,v2) or does it wait to the list to be exhausted?)
sort([5])=v1 sort ([4,2])=v2
(because the length of v1 is less than 1 then returns v which is [5], in this part I do not know how it gets joined with v2)
v[5]     sort(v[4])=v1  sort(v[2]))
(v[5] has been returned and the right part gets ordered so we will have v=[2,4])

在最后一部分中,我只是不知道是否应该用v[5]和v=[2,4]调用merge来进行排序,是这样吗?还是我错过了什么?

有什么帮助或如何正确解释此源代码吗?

感谢

为了演示mergesort是如何工作的,我展示了我自己的实现,我写了一段时间:

def mergesort(lst):
# SORT PART ------------------------------------------------
# base case: return just this list if length = 1
if len(lst) <= 1:
return lst
# recursive case: do mergesort() on either half of the list
mid = len(lst) // 2
sub1, sub2 = mergesort(lst[:mid]), mergesort(lst[mid:])
# MERGE PART ------------------------------------------------
# merge sub1 and sub2, which are each sorted
sorted_lst = []
while sub1 and sub2:  # ...are not empty...
# remove the lesser element from the front of sub1 or sub2 and add it to sorted list
sorted_lst.append(sub1.pop(0) if sub1[0] < sub2[0] else sub2.pop(0))
# finally, once one of the lists are empty, append the remainder of the other list.
sorted_lst += (sub1 if sub1 else sub2)
# and return the now-sorted list
return sorted_lst

从本质上讲,mergesort会重复地将列表一分为二,直到它到达单例列表。在这一点上,它将较低的元素放在较高的元素之前并返回。

然后,下一级考虑它返回的两个列表,并将它们都视为优先级队列-删除它们之间的最低元素,然后删除它们之间下一个最低元素,等等。所述最低元素总是在前面,因为较低的递归层是这样做的。

在自上而下的合并排序中,只有在子数组大小减少到单个元素的两种基本情况下,合并才会开始。在那之后,合并和拆分在调用链上下继续,深度优先,通常是左优先。

对于问题示例代码,递归将重复遵循排序的左路径(v[:mid](,直到到达基本情况一个元素,然后该实例返回以允许第二次调用排序(v[mid:](,这可能是两个元素,在这种情况下,会发生一个更高级别的递归,然后开始合并。

最新更新