我已经使用codereview上的帖子实现了mergesort算法。它在整数列表上工作得很好,但我认为需要一个更实际的应用程序。所以我下载了一个带有随机英文单词的文本文件,并尝试对它们进行排序。
然而它绝对没有。
save
我认为问题在于它处理的是列表而不是单个列表。此功能也无法知道排序的基础是什么。这是对的吗?
以下是我想要的方式
def merge_sort(seq):
if len(seq) == 1:
return seq
else:
# recursive step. Break the list into chunks of 1
mid_index = len(seq) // 2
left = merge_sort( seq[:mid_index] )
right = merge_sort( seq[mid_index:] )
left_counter, right_counter, master_counter = 0, 0, 0
while left_counter < len(left) and right_counter < len(right):
if left[left_counter] < right[right_counter]:
seq[master_counter] = left[left_counter]
left_counter += 1
else:
seq[master_counter] = right[right_counter]
right_counter += 1
master_counter += 1
# Handle the remaining items in the remaining_list
# Either left or right is done already, so only one of these two
# loops will execute
while left_counter < len(left): # left list isn't done yet
seq[master_counter] = left[left_counter]
left_counter += 1
master_counter += 1
while right_counter < len(right): # right list isn't done yet
seq[master_counter] = right[right_counter]
right_counter += 1
master_counter += 1
return seq
答案 0 :(得分:3)
正如您所发现的那样,问题是merge_sort
无法知道排序的基础。您可以更改merge_sort
以接收另一个参数,该参数返回序列中每个元素的键,就像sorted
一样:
def merge_sort(seq, key=lambda x: x):
然后将比较更改为调用传递函数而不是直接比较元素:
if key(left[left_counter]) < key(right[right_counter]):
seq[master_counter] = left[left_counter]
left_counter += 1
else:
seq[master_counter] = right[right_counter]
right_counter += 1
最后将密钥传递给递归调用:
left = merge_sort( seq[:mid_index], key )
right = merge_sort( seq[mid_index:], key )
通过这些更改,它可以按预期工作:
merge_sort([4, 6, 2, 1]) # [1, 2, 4, 6]
merge_sort(['foo', 'a', 'bar', 'foobar'], key=len) # ['a', 'bar', 'foo', 'foobar']
有一点需要注意的是,结果与sorted
不一致,因为merge_sort
不是stable:
merge_sort(['foo', 'a', 'bar', 'foobar'], key=len) # ['a', 'bar', 'foo', 'foobar']
sorted(['foo', 'a', 'bar', 'foobar'], key=len) # ['a', 'foo', 'bar', 'foobar']