以下是list-based
quicksort的实现:
let partition pivot l =
let rec p left right = function
| [] -> (left, right)
| hd::tl ->
let c = compare pivot hd
in
if c > 0 then
p (hd::left) right tl
else
p left (hd::right) tl
in
p [] [] l;;
let quicksort l =
let rec qs = function
| [] -> []
| pivot::tl ->
let (left, right) = partition pivot tl
in
(qs left) @ (pivot::(qs right))
in
qs l;;
当我使用100,000
列表进行尝试时,它很好并且没有问题。
但是,如果我使用1,000,000
进行尝试,则会出现stack_overflow
错误。
我不明白为什么它会给stack_overflow
,因为我认为堆栈大小应该像log1000000 ~ 20
一样,对吧?
答案 0 :(得分:5)
我会假设@
运算符将使用线性数量的堆栈。 (这只是在列表上进行快速排序的问题之一。)
以下是Pervasives模块中@
的定义:
let rec ( @ ) l1 l2 =
match l1 with
[] -> l2
| hd :: tl -> hd :: (tl @ l2)
这是一个非常缓慢的排序。如果你真的想要这个,你必须要聪明得多。至少你需要一个尾递归版@
。
答案 1 :(得分:1)
Quicksort不能用于链接列表。它不起作用好。在列表上使用的正确排序算法是合并排序。 基本上,只要在算法中使用列表连接,就应该意识到你做得不对,或者你应该使用其他数据结构。列表有许多优点,连接不是其中之一。
答案 2 :(得分:0)
如前所述,问题在于@。这不是一个无法解决的问题:您需要将内部排序函数重新定义为一个排序和连接的函数。
let partition pivot l =
let rec p left right = function
| [] -> (left, right)
| hd::tl ->
let c = compare pivot hd
in
if c > 0 then
p (hd::left) right tl
else
p left (hd::right) tl
in
p [] [] l;;
let quicksort l =
let rec qs l acc =
match l with
| [] -> acc
| pivot::tl ->
let (left, right) = partition pivot tl
in
qs left (pivot::(qs right acc))
in
qs l [];;