我在OCaml中实现了non-in-place
版本的选择排序。
let sort compare_fun l =
let rec find_min l' min_l origin_l =
match l' with
| [] ->
if min_l = [] then (min_l, l')
else
let min = List.hd min_l
in
(min_l, List.filter (fun x -> if x != min then true else false) origin_l)
| x::tl ->
if min_l = [] then
find_min tl [x] origin_l
else
let c = compare_fun (List.hd min_l) x
in
if c = 1 then
find_min tl [x] origin_l
else if c = 0 then
find_min tl (min_l @ [x]) origin_l
else
find_min tl min_l origin_l
in
let rec insert_min l' new_l =
match l' with
| [] -> new_l
| _ ->
let (min_l, rest) = find_min l' [] l'
in
insert_min rest (new_l @ min_l)
in
insert_min l [];;
我的想法是,在列表中,每次找到最小项目列表(如果是重复值)并将此min list
添加到结果列表,然后在列表的其余部分重做lookup_min
我使用List.filter
过滤掉min_list
,因此结果列表将成为下一个find_min
的列表。
我发现我的实现非常复杂,而且远比Java就地版本的选择排序复杂。
有任何改进建议吗?
答案 0 :(得分:1)
编辑:这是一个更好的实施:http://rosettacode.org/wiki/Sorting_algorithms/Selection_sort#OCaml
这是我自己更糟糕的实现
(* partial function - bad habit, don't do this. *)
let smallest (x::xs) = List.fold_right (fun e acc -> min e acc) xs x
let remove l y =
let rec loop acc = function
| [] -> raise Not_found
| x::xs -> if y = x then (List.rev acc) @ xs else loop (x::acc) xs
in loop [] l
let selection_sort =
let rec loop acc = function
| [] -> List.rev acc
| xs ->
let small = smallest xs in
let rest = remove xs small in
loop (small::acc) rest
in loop []