I'm not going to go into details about how the following works right now, but it's a backtracking iterator I wrote for n-ary trees.
type path = Down | Up | Entry of int exception End_of_Traversal (* Preorder traversal of an n-ary tree. checked *) let preorder t = let rec aux = function E -> [] | N (x, []) -> [Entry x] | N (x, children) -> let result = List.fold_left (fun accum c -> match (aux c) with [] -> accum | x -> Up::x @ Down::accum ) [] children in result @ [Entry x] in List.rev (aux t) (* postorder ie depth-first, checked *) let postorder t = let rec aux accum = function E -> [] | N (x, []) -> [Entry x] | N (x, children) -> let result = List.fold_left (fun accum c -> match (aux [] c) with [] -> accum | x -> Up::x @ Down::accum ) [] children in (Entry x)::result in List.rev (aux [] t) (*Now the same functions can be used for going forward and backward in the traversal, whatever traversal you chose.*) let rec forward = function ([],_) -> raise End_of_Traversal | Up::(Entry x)::xx, history -> (Entry x)::xx, Down::history | Down::(Entry x)::xx, history -> (Entry x)::xx, Up::history | Up::x::xx, history -> forward (x::xx, Down::history) | Down::x::xx, history -> forward (x::xx, Up::history) | x, history -> forward (List. tl x, (List.hd x)::history) let rec backward = function (_, []) -> raise End_of_Traversal | (current, Up::history) -> backward (Down::current, history) | (current, Down::history) -> backward (Up::current, history) | (current, x::xx) -> (x::current, xx) let rewind (current, history) = List.rev_append (invert history) current let extract (current, history) = try match List.hd current with Up | Down -> None | Entry x -> Some x with (Failure "hd") -> raise End_of_Traversal
1 comment:
Keep posting stuff like this i really like it
Post a Comment