[英]How do I make this Merge Sort function a generator (Python)?
所以我了解如何在 Python 3 中进行合并排序算法,这是我下面用于实现 function 的代码:
def x(arr):
for i in mergeSort(arr):
yield from i
def mergeSort(arr):
if len(arr) > 1:
middle = len(arr) // 2
left = arr[:middle]
right = arr[middle:]
mergeSort(left)
mergeSort(right)
a = 0
b = 0
c = 0
while a < len(left) and b < len(right):
if left[a] < right[b]:
arr[c] = left[a]
a += 1
else:
arr[c] = right[b]
b += 1
c += 1
while a < len(left):
arr[c] = left[a]
a += 1
c += 1
while b < len(right):
arr[c] = right[b]
b += 1
c += 1
for i in mergeSort([6,3,8,7,4,1,2,9,5,0]):
print(i)
它的要点是 function 返回最后排序的数组。 但是,我正在尝试构建一个排序可视化器,为此,我需要让这个 function 在进行更改时产生数组,以便您可以看到条形开关 -所以我需要将其设为 generator ,但所有尝试我已经这样做了,但没有奏效。 如何修改我的代码以使此 function 成为生成器?
谢谢。
首先,您需要确保深度递归执行实际上可以报告整个列表的 state。 使用您当前的设置是不可能的,因为递归 function 只能看到数组的一小部分。
因此,为了解决这种情况,不要通过递归调用传递切片,而是传递开始/结束索引,从而为所有 function 执行上下文提供对相同arr
的访问权限。
然后你可以在每次合并后yield arr
。 进行递归调用的代码应使用yield from
。
我修改了您的代码只是为了应用上述想法:
def mergeSort(arr):
# arr is a unique list that all levels in the recursion tree can access:
def mergeSortRec(start, end): # separate function that can take start/end indices
if end - start > 1:
middle = (start + end) // 2
yield from mergeSortRec(start, middle) # don't provide slice, but index range
yield from mergeSortRec(middle, end)
left = arr[start:middle]
right = arr[middle:end]
a = 0
b = 0
c = start
while a < len(left) and b < len(right):
if left[a] < right[b]:
arr[c] = left[a]
a += 1
else:
arr[c] = right[b]
b += 1
c += 1
while a < len(left):
arr[c] = left[a]
a += 1
c += 1
while b < len(right):
arr[c] = right[b]
b += 1
c += 1
yield arr
yield from mergeSortRec(0, len(arr)) # call inner function with start/end arguments
for i in mergeSort([6,3,8,7,4,1,2,9,5,0]):
print(i)
对于示例列表,output 如下:
[3, 6, 8, 7, 4, 1, 2, 9, 5, 0]
[3, 6, 8, 4, 7, 1, 2, 9, 5, 0]
[3, 6, 4, 7, 8, 1, 2, 9, 5, 0]
[3, 4, 6, 7, 8, 1, 2, 9, 5, 0]
[3, 4, 6, 7, 8, 1, 2, 9, 5, 0]
[3, 4, 6, 7, 8, 1, 2, 9, 0, 5]
[3, 4, 6, 7, 8, 1, 2, 0, 5, 9]
[3, 4, 6, 7, 8, 0, 1, 2, 5, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
您可以决定还产生开始/结束索引,以便迭代器的使用者知道算法在哪里操作列表。 所以然后改变:
yield arr
至:
yield arr, start, end
随着这一变化,output 变为:
([3, 6, 8, 7, 4, 1, 2, 9, 5, 0], 0, 2)
([3, 6, 8, 4, 7, 1, 2, 9, 5, 0], 3, 5)
([3, 6, 4, 7, 8, 1, 2, 9, 5, 0], 2, 5)
([3, 4, 6, 7, 8, 1, 2, 9, 5, 0], 0, 5)
([3, 4, 6, 7, 8, 1, 2, 9, 5, 0], 5, 7)
([3, 4, 6, 7, 8, 1, 2, 9, 0, 5], 8, 10)
([3, 4, 6, 7, 8, 1, 2, 0, 5, 9], 7, 10)
([3, 4, 6, 7, 8, 0, 1, 2, 5, 9], 5, 10)
([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 0, 10)
也许是这样的:
def x(arr):
for i in mergeSort(arr):
yield i
def mergeSort(arr):
if len(arr) > 1:
middle = len(arr) // 2
left = arr[:middle]
right = arr[middle:]
mergeSort(left)
mergeSort(right)
a = 0
b = 0
c = 0
while a < len(left) and b < len(right):
if left[a] < right[b]:
arr[c] = left[a]
a += 1
else:
arr[c] = right[b]
b += 1
c += 1
while a < len(left):
arr[c] = left[a]
a += 1
c += 1
while b < len(right):
arr[c] = right[b]
b += 1
c += 1
return arr
# Entry point
generator = x([6,3,8,7,4,1,2,9,5,0])
print(next(generator)) # prints 0
print(next(generator)) # prints 1
# print the remaining elements
for i in generator:
print(i)
Output:
0
1
2
3
4
5
6
7
8
9
请注意,您可以使用的合并排序的较短递归实现可能如下:
def merge_sort(mylist):
if len(mylist) < 2:
return mylist
less = []
equal = []
greater = []
n = int(len(mylist)/2)
pivot = mylist[n]
for x in mylist:
if x < pivot:
less.append(x)
elif x == pivot:
equal.append(x)
elif x > pivot:
greater.append(x)
return merge_sort(less) + equal + merge_sort(greater)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.