【问题标题】:Efficient solution for merging 2 sorted lists in Python在 Python 中合并 2 个排序列表的有效解决方案
【发布时间】:2018-01-21 04:45:42
【问题描述】:

我从 Google 发布的速成课程开始自学 Python。练习题之一是编写一个函数,它接受 2 个 sorted 列表,将它们合并在一起,然后返回一个有序列表。最明显的解决方案是:

def linear_merge(list1, list2):
  list = list1 + list2
  list.sort()
  return list

显然上面的效率不是很高,或者我是这么认为的,因为在后端,排序函数将不得不再次遍历整个输出列表。问题需要一种有效的方法来实现这个功能,大概它可以在巨大的列表上很好地工作。我的代码类似于 Google 的答案,但我对其进行了一些调整以使其更快:

def linear_merge_goog(list1, list2):
  result = []
  while len(list1) and len(list2):
    if list1[-1] > list2[-1]:
      result.append(list1.pop())
    else:
      result.append(list2.pop())

  result.extend(list1)
  result.extend(list2)
  return result[::-1]

原始的 Google 代码是从数组的前面弹出的,但即使他们也注意到从数组的后面弹出而不是反转它更有效。

我尝试用 2000 万个大型条目数组运行这两个函数,而简单愚蠢的组合和排序函数每次都以 3 倍以上的优势排在首位。对于应该更有效的方法,不到 1 秒与超过 3 秒。

有什么想法吗?我是不是错过了什么。它是否与在解释我的代码时编译的内置排序函数有关(听起来不太可能)。还有其他想法吗?

【问题讨论】:

  • 所以你说线性合并更快?这两个子列表是排序的,对吧?
  • 另外,很有可能。 python timsort 代码是用 C 编写的,经过高度优化,速度非常快,尤其是对于几乎排序的列表。相反,在非连续结构上执行操作的合并速度很慢。它不太可能更快。
  • 是的,2 个子列表已排序,因此排序方法应该比手动合并慢,但事实并非如此,它要快得多。正如你提到的,我认为这只是 C 的优势。

标签: python arrays list sorting performance-testing


【解决方案1】:

这是因为 .sort() 的 Python 实现。 Python 使用名为 Timsort 的东西。

Timsort 是一种归并排序。它的显着特征是它识别用于合并的预排序数据的“运行”。在现实世界的数据中,未排序数据中的排序运行非常常见,如果它们是预排序的,您可以在 O(n) 时间内对两个排序数组进行排序。这可以大大减少通常在 O(nlog(n)) 时间内运行的排序时间。

所以发生的情况是,当您在 Python 中 call list.sort() 时,它会识别两次运行的排序数据 list1list2,并在 O(n) 时间内将它们合并。此外,这个实现是编译的 C 代码,它比解释的 Python 实现做同样的事情要快。

【讨论】:

  • 我认为Tim Peters 会对这个答案感到非常满意。 ;)
猜你喜欢
  • 1970-01-01
  • 2019-02-05
  • 1970-01-01
  • 2018-03-11
  • 1970-01-01
  • 2011-05-17
  • 2020-12-21
  • 1970-01-01
  • 2014-06-08
相关资源
最近更新 更多