使用列表时elixir的性能改进

时间:2016-07-17 01:49:02

标签: elixir

如何在例如mergesort中提高性能。在mergesort的合并步骤中,将大小为n / 2的较小列表组合成大小为n的列表。因为这是递归发生的,所以调用下一个tiem merge来合并2个数组,这些列表的大小为n,新列表的大小为2n。在Elixir列表是不可变的我不能修改初始列表的值,我试图排序的列表。相反,它会在合并的每个步骤创建新列表。我怎样才能改善这个?会使用ets吗?

2 个答案:

答案 0 :(得分:2)

Elixir已经解决了很多这样的性能问题。以mergesort中的合并为例,我们有:lists.merge采用预先排序的数组,并返回一个已排序的数组。完全合并排序可能如下所示:

defmodule Sort do
  def merge_sort(input) when length(input) <= 1 do
    input
  end

  def merge_sort(input) do
    splitting_point = length(input) |> div(2)
    { left, right } = Enum.split(input, splitting_point)
    :lists.merge(merge_sort(left), merge_sort(right))
  end
end

我写的Elixir有很多东西排序好了吧? mergesort也不例外。您可以使用引擎盖下使用mergesort的Enum.sort,并将其称为一天。

答案 1 :(得分:0)

这是我对归并排序的实现,它的价值所在。

请注意,这只是一个练习。正如奥拉夫所说,Enum.sort/1(以及下面的 :lists.sort/1)已经实现了归并排序。此处的 npm install -g serve 函数也可以替换为 :lists.merge/2。不过那些是在 Erlang 中实现的,所以很高兴看到一个纯 Elixir 版本。

注意事项:

  1. 在构建合并列表时,添加到列表的前面,并且只 merge 一次以避免每次添加都遍历列表。
  2. 对于合并,一旦合并的一侧为空,我们就知道其余未合并的元素已经排序,可以直接附加到结果中(使用 Enum.reverse())。
  3. 据我所知,由于语言的不变性,没有办法避免创建中间列表。这就是为什么像快速排序这样的就地算法不是默认算法的原因。
++