Вопрос
1 Потоки и ленивая оценка (40 баллов)
Мы знаем, что сортировка сравнением требует как минимум O(n log n) сравнений, где were сортирует n элементов. Допустим, нам нужны только первые f(n) элементов из отсортированного списка для некоторой функции f. Если мы знаем, что f(n) асимптотически меньше, чем log n, то было бы расточительно сортировать весь список. Мы можем реализовать ленивую сортировку, которая возвращает поток, представляющий отсортированный список. Каждый раз, когда к потоку обращаются для получения заголовка отсортированного списка, в списке находится наименьший элемент. Это занимает линейное время. Удаление элементов f(n) из списка займет O(nf(n)). Для этого вопроса мы используем следующие определения типов данных. Также определены некоторые вспомогательные функции.
(* Suspended computation *) datatype 'a stream' = Susp of unit -> 'a stream (* Lazy stream construction *) and 'a stream = Empty | Cons of 'a * 'a stream'
Обратите внимание, что эти потоки не обязательно бесконечны, но могут быть.
Q1.1 (20 баллов) Реализовать функцию lazysort: int list -> int stream'.
Он принимает список целых чисел и возвращает целочисленный поток, представляющий отсортированный список. Это должно быть сделано в постоянное время. Каждый раз, когда поток 'форсируется', он дает либо Empty, либо Cons(v, s'). В случае минусов v — это наименьший элемент из отсортированного списка, а s — это поток, представляющий оставшийся отсортированный список. Сила должна принимать линейное время. Например:
- val s = lazysort( [9, 8, 7, 6, 5, 4] ); val s = Susp fn : int stream' - val Cons(n1, s1) = force(s); val n1 = 4 : int val s1 = Susp fn : int stream' - val Cons(n2, s2) = force(s1); val n2 = 5 : int val s2 = Susp fn : int stream' - val Cons(n3, s3) = force(s2); val n3 = 6 : int val s3 = Susp fn : int stream'
Соответствующие определения
Вот что дано в виде кода:
(* Suspended computation *) datatype 'a stream' = Susp of unit -> 'a stream (* Lazy stream construction *) and 'a stream = Empty | Cons of 'a * 'a stream' (* Lazy stream construction and exposure *) fun delay (d) = Susp (d) fun force (Susp (d)) = d () (* Eager stream construction *) val empty = Susp (fn () => Empty) fun cons (x, s) = Susp (fn () => Cons (x, s)) (* Inspect a stream up to n elements take : int -> 'a stream' -> 'a list take': int -> 'a stream -> 'a list *) fun take 0 s = [] | take n (s) = take' n (force s) and take' 0 s = [] | take' n (Cons (x, xs)) = x::(take (n-1) xs)
Моя попытка решения
Я попытался сделать следующее, чтобы получить список int и преобразовать его в поток int:
(* lazysort: int list -> int stream' *)
fun lazysort ([]:int list) = empty
| lazysort (h::t) = cons (h, lazysort(t));
Но при вызове force он не возвращает минимальный элемент. Мне нужно найти минимум, но я не знаю, как... Я подумал о том, чтобы сделать сортировку вставки следующим образом:
fun insertsort [] = []
| insertsort (x::xs) =
let fun insert (x:real, []) = [x]
| insert (x:real, y::ys) =
if x<=y then x::y::ys
else y::insert(x, ys)
in insert(x, insertsort xs)
end;
Но я должен искать минимум и не сортировать список, а затем помещать его в поток...
Любая помощь будет оценена по достоинству.