【问题标题】:How can built-in sorting algorithm be so fast?内置排序算法怎么会这么快?
【发布时间】:2016-08-17 15:44:02
【问题描述】:

Quicksort 据说是用于在列表/表格/任何内容中对数据进行排序的最快速算法之一。反正这个算法的rosettacode Lua实现是怎么来的

function quicksort(t)
    if #t < 2 then return t end
    local pivot = t[1]
    local a, b, c={}, {}, {}
    for _, v in ipairs(t) do
        if v < pivot then a[#a + 1] = v
        elseif v > pivot then c[#c + 1] = v
        else b[#b + 1] = v
        end
    end
    a = quicksort(a)
    c = quicksort(c)
    for _, v in ipairs(b) do a[#a + 1] = v end
    for _, v in ipairs(c) do a[#a + 1] = v end
    return a
end

与内置的table.sort(table) 算法相比,速度要慢得多(大约需要一分钟才能对一百万个条目表中的所有随机放置的条目进行排序),而对同一个表进行排序只需要大约五秒钟?

【问题讨论】:

  • Lua 是解释型语言,解释成本高。与本机代码进行比较时,至少尝试使用 LuaJIT 进行相同的测试。
  • 快速排序在最佳和平均情况下为 O(n log n),但在最坏情况下为 O(n ^ 2)。并不总是最快速的算法。
  • @Akshat Mahajan 不过,这并不能解释效率的多少损失,如果我以另一个顺序重新创建表,我会得到大致相同的结果。
  • @Vlad JIT 编译器有什么变化?
  • 用C写,会更快。

标签: sorting lua quicksort lua-table rosetta-code


【解决方案1】:

内置的table.sort 也使用快速排序算法。 (见its code

主要区别在于,内置的语言是用 C 编写的。虽然 Lua 比其他脚本语言快,但仍不如 C。

【讨论】:

  • 所以 C 比 Lua 快(这是有道理的)。但是 C++ 呢?
  • @user6245072 C++ 仍然会更快。您无法将脚本语言与编译语言进行比较。然而,像已经提到的 LuaJIT 编译器和 Terra (terralang.org) 之类的东西,你可以使用它们来非常接近,因为它们在下面使用 C。
  • 解释与编译,而不是脚本与编译。即使作为脚本语言,Lua 在解释方面也胜过 Python。
【解决方案2】:

您应该将您的支点设置为 t[2],使我的编译器的性能翻倍,但根据您实现快速排序的方式,它可能会破坏它。

【讨论】:

    【解决方案3】:

    除了语言的不同,Lua 内置的table.sort 就地修改了目标表。您的实现返回一个新表,每个迭代步骤实例化 3 个新表。我认为这就是大部分性能丢失的地方。在对包含数百万个项目的数组进行排序时,这些额外的表分配会迅速增加!

    更合适的比较是就地快速排序

    local quicksort do
      local function qhelp(t, l, r)
        if r - l < 1 then return end
        local p = l
        for i = l + 1, r do
          if t[i] < t[p] then
            if i == p + 1 then
              t[p],t[p+1] = t[p+1],t[p]
            else
              t[p],t[p+1],t[i] = t[i],t[p],t[p+1]
            end
            p = p + 1
          end
        end
        qhelp(t, l, p - 1)
        qhelp(t, p + 1, r)
      end
    
      function quicksort(t)
        qhelp(t, 1, #t)
      end
    end
    

    用法:

    local arr = { 1, 5, 2, 17, 11, 3, 1, 22, 2, 37 }
    quicksort(arr)
    print(table.concat(arr,","))
    

    请注意,如果无法修改输入表,则将其复制到牺牲表并就地排序也将比“纯”实现更快。

    【讨论】:

    • 我从未见过以这种方式使用do 来防止辅助变量污染命名空间。感谢分享!
    猜你喜欢
    • 1970-01-01
    • 2012-02-17
    • 2020-12-19
    • 2011-06-02
    • 2012-03-18
    • 2012-05-18
    • 1970-01-01
    • 2020-11-22
    • 2011-02-01
    相关资源
    最近更新 更多