【发布时间】:2012-06-27 10:44:03
【问题描述】:
使用 F# List 和 Seq 合并两个排序的列表/序列。这些值是通过从辅助存储器中读取两个文件获得的 - 文件读取的结果存储在两个序列中。假设存储整数用于测试目的,现在尝试使用以下代码合并这些以打印出排序序列:
let rec printSortedSeq l1 l2 =
match ( l1, l2) with
| l1,l2 when Seq.isEmpty l1 && Seq.isEmpty l2 -> printfn "";
| l1, l2 when Seq.isEmpty l1 -> printf "%d " (Seq.head l2); printSortedSeq l1 (Seq.skip 1 l2);
| l1, l2 when Seq.isEmpty l2-> printf "%d " (Seq.head l1); printSortedSeq (Seq.skip 1 l1) [];
| l1,l2 -> if Seq.head l1 = Seq.head l2 then printf "%d " (Seq.head l1); printSortedSeq (Seq.skip 1 l1) (Seq.skip 1 l2);
elif Seq.head l1 < Seq.head l2 then printf "%d " (Seq.head l1); printSortedSeq (Seq.skip 1 l1) (Seq.skip 1 l2);
else printf "%d " (Seq.head l2); printSortedSeq (Seq.skip 1 l1) (Seq.skip 1 l2);
该代码最初是为了合并两个排序列表而编写的:
let rec printSortedList l1 l2 =
match ( l1, l2) with
| h1 :: t1 , h2 :: t2 -> if h1 = h2 then printf "%d " h1; printSortedList t1 t2;
elif h1 < h2 then printf "%d " h1; printSortedList t1 l2;
else printf "%d " h2; printSortedList l1 t2;
| [] , h2 :: t2 -> printf "%d " h2; printSortedList [] t2;
| h1 :: t1, [] -> printf "%d " h1; printSortedList t1 [];
| [], [] -> printfn"";
与列表相比,使用它们的性能大大提高。我在做#time之后给出计时结果;;在 FSI 中进行一些试验输入。
let x = [0..2..500];
let y = [1..2..100];
let a = {0..2..500}
let b = {1..2..100}
printSortedList x y;; 真实:00:00:00.012,CPU:00:00:00.015
printSortedSeq a b;; 真实:00:00:00.504,CPU:00:00:00.515
问题是 - 有没有办法使用序列来加快速度?因为虽然列表要快得多,但由于提供输入的文件非常大(> 2 GB),它们不适合主内存,所以我从文件中读取值作为惰性序列。在合并之前将它们转换为列表有点违背了整个目的。
【问题讨论】:
-
你是如何测量时间的?看起来你也在计时打印代码,那自然会很慢。
-
两个序列(见下面我的答案)和惰性列表合并应该在
O(1)内存和O(N1+N2)时间运行。在这一点上,只有一个恒定的因素差异 - 在优化它的每一点之前,在你的输入上尝试最简单的解决方案,看看它是否足够好。