- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我的快速排序代码适用于 N(列表大小)的某些值,但对于大值(例如,N = 82031),OCaml 返回的错误是:
Fatal error: exception Stack_overflow.
我做错了什么?
由于 OCaml 不支持大值的递归函数,我是否应该创建一个迭代版本?
let rec append l1 l2 =
match l1 with
| [] -> l2
| x::xs -> x::(append xs l2)
let rec partition p l =
match l with
| [] -> ([],[])
| x::xs ->
let (cs,bs) = partition p xs in
if p < x then
(cs,x::bs)
else
(x::cs,bs)
let rec quicksort l =
match l with
| [] -> []
| x::xs ->
let (ys, zs) = partition x xs in
append (quicksort ys) (x :: (quicksort zs));;
最佳答案
问题是你的递归函数都不是尾递归的。
尾递归意味着调用者不应执行进一步的操作(参见 here )。在那种情况下,不需要保留调用函数的环境,堆栈也不会充满递归调用的环境。像 OCaml 这样的语言可以以最佳方式编译它,但为此您需要提供尾递归函数。
例如,您的第一个函数 append
:
let rec append l1 l2 =
match l1 with
| [] -> l2
| x::xs -> x::(append xs l2)
如你所见,append xs l2
被调用后,调用者需要执行 x::...
并且这个函数最终不是 tail -递归。
另一种尾递归方式是这样的:
let append l1 l2 =
let rec aux l1 l2 =
match l1 with
| [] -> l2
| x::xs -> append xs (x :: l2)
in aux (List.rev l1) l2
但是,实际上,你可以尝试使用List.rev_append
知道此函数将附加 l1
和 l2
但 l1
将被反转(List.rev_append [1;2;3] [ 4;5;6]
给出 [3;2;1;4;5;6]
)
尝试将您的其他函数转换为尾递归函数,看看它能给您带来什么。
关于ocaml - 递归函数中大整数的异常 Stack_overflow,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44657319/
我的快速排序代码适用于 N(列表大小)的某些值,但对于大值(例如,N = 82031),OCaml 返回的错误是: Fatal error: exception Stack_overflow. 我做错
所以我刚刚来到书中解释堆栈的部分。以下是它们在我的书中的定义方式(代码): #include #define STACK_SIZE 100 int contents[STAC_SIZE] int t
我想问下exception :"exception Stack_overflow"是否会导致死循环,特别是异常出现在下面的代码中: ( *the loop "while" should sto
如果在 .dll 中使用此代码, 对 socket.recv() 的调用会引发一个异常 STACK_OVERFLOW,但是当此代码编译为 .exe 时,它可以正常工作。 为什么? 我通过“C:\win
我是一名优秀的程序员,十分优秀!