我试图在prolog中编写一些排序算法,并在我开始考虑它们是否会因为它们是用逻辑语言编写时会有不同的复杂性时发现它们的复杂性。
以快速排序为例。它的平均复杂度为nlogn,它的代码(不完整)如下所示:
quicksort([Head|Tail], SortedList) :-
split(Head, Tail, Left, Right),
quicksort(Left, SortedLeft),
quicksort(Right, SortedRight),
append(SortedLeft, [Head|SortedRight], SortedList).
分裂有n。快速登录。这给出了(平均值)nlogn。但是追加呢?它也具有线性复杂性。总体而言(n ^ 2)logn是什么?
没有这样的事实:在prolog中我们只能以线性方式访问列表元素,这会损害我们程序的复杂性。从这个意义上来说,使用像C这样的另一种语言是不是更好?
答案 0 :(得分:3)
在确定算法的复杂性时,您应采取与其他语言相同的步骤,并记住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中,quicksort可以用O(lg n)''space''复杂度编写,因为你只需要表示堆栈并可以就地修改数组。相比之下,Prolog列表是不可变的,因此您的程序将构建一个新列表并具有线性空间复杂性。这种好坏取决于用例。