【问题标题】:Complexity of sorting algorithms in PrologProlog中排序算法的复杂性
【发布时间】:2014-06-01 21:56:29
【问题描述】:

我试图在 prolog 中编写一些排序算法并发现它们的复杂性,当我开始考虑它们是否会因为它们是用逻辑语言编写的而具有不同的复杂性时。

以快速排序为例。它的平均复杂度为 nlogn,其代码(不完整)如下所示:

quicksort([Head|Tail], SortedList) :-
    split(Head, Tail, Left, Right),
    quicksort(Left, SortedLeft),
    quicksort(Right, SortedRight),
    append(SortedLeft, [Head|SortedRight], SortedList).

split 有 n。快速排序登录。这给出了(平均)nlogn。但是追加呢?它还具有线性复杂性。那么整体是 (n^2)logn 吗?

在 prolog 中我们只能以线性方式访问列表的元素这一事实是否会损害我们程序的复杂性。从这个意义上说,使用另一种语言(例如 C)不是更好吗?

【问题讨论】:

标签: sorting prolog complexity-theory


【解决方案1】:

在确定算法的复杂性时,您应该采取与其他语言相同的步骤,并记住 Prolog 程序具有程序性/命令式阅读以及逻辑阅读。主要区别在于回溯的可能性,在这种情况下,这不是很相关。

这个程序的复杂性,假设没有任何步骤回溯,由递归给出

T(n) ≤ 2T(n/2) + splitT(n) + appendT(n)

您已经观察到append/3 需要线性时间,所以如果split/4 也需要线性时间,

splitT(n) + appendT(n) = Θ(n)

你会得到 T(n) ≤ 2T(n/2) + Θ(n),这与命令式快速排序相同。

在 prolog 中我们只能以线性方式访问列表的元素这一事实是否会损害我们程序的复杂性。从这个意义上说,使用另一种语言(例如 C)不是更好吗?

正如我所展示的,这与您提出的复杂性问题无关。是的,对于许多问题,惯用的 C 程序比惯用的 Prolog 程序快。对于其他问题,惯用的 Prolog 程序是几行代码,而相应的 C 程序将包含半个 Prolog 解释器。

这里的相关之处在于,在 C 中,可以使用 O(lg n) ''space'' 复杂度编写快速排序,因为您只需要表示堆栈并且可以就地修改数组。相比之下,Prolog 列表是不可变的,因此您的程序将构建一个新列表并具有线性空间复杂度。这是好是坏取决于用例。

【讨论】:

  • 这是最坏的情况,让快速排序令人生畏。而且我也相信它的不稳定性(不知道如何通过合理的努力来解决这个问题)
  • @false 最坏的情况在introsort 变体中更好,但为此你需要堆,而这些在 Prolog 中也很重要。
  • 我刚刚检查了wikipedia,发现这与我记忆中的不同。我的意思是合并排序的改进版本,您首先扫描可以线性排序的前缀:所以 [1,-1,2,-2,3,-4|...] 将是 one 线性扫描。这在 Prolog 中是可能的,但在函数式语言中是不可能的。
  • Some reference 这个精炼的归并排序。
  • 如何从 [1,-1,2,-2,3,-4] 中产生 [-4,-3,-2,-1,1,2,3]?
猜你喜欢
  • 1970-01-01
  • 2010-12-19
  • 2017-12-19
  • 2021-08-22
  • 1970-01-01
  • 2015-01-05
  • 1970-01-01
  • 2022-01-13
相关资源
最近更新 更多