From: Brian Hurt <brian.hurt@qlogic.com>
To: Stalkern 2 <stalkern2@tin.it>
Cc: <caml-list@inria.fr>
Subject: Re: [Caml-list] tree walking with... specular rec functions? what else?
Date: Fri, 9 May 2003 10:23:20 -0500 (CDT) [thread overview]
Message-ID: <Pine.LNX.4.33.0305090959170.2037-100000@eagle.ancor.com> (raw)
In-Reply-To: <200305091156.47892.stalkern2@tin.it>
On Fri, 9 May 2003, Stalkern 2 wrote:
> Hello to everybody
>
> I've a simple tree structure and I want to walk it. Since in such a simple
> tree structure I can go AFAIK only sidewards or upwards/downwards, and I need
> to do both, I guess what can be an efficent way to do so.
Recursion is your friend. Let's assume we have a type like:
type 'a tree = Leaf
| Node of 'a * 'a tree * 'a tree
This is the most basic of tree data structures. Data can be held in any
node, the bottom of the tree is marked by leafs. We want to define a walk
function, which calls a function f on all elements of the tree, in a
depth-first pattern. This is simple:
let rec walk f tree =
match tree with
Leaf -> ()
| Node(data, left, right) ->
walk f left;
f data;
walk f right
;;
Obvious variations include which order you evaluate the last three
statements as. Equally valid would be: f data; walk f left; walk f right;
and walk f left; walk f right; f data; .
Doing a breadth first is a little bit more tricky, as you have to keep a
list of the next nodes down:
let rec walk f tree =
let rec inner lst accum =
match lst with
[] -> List.rev accum
| Leaf :: t -> inner t accum
| Node(data, left, right) :: t ->
f data;
inner t (right :: left :: accum)
in
let rec outer lst =
if (List.length lst) == 0 then ()
else outer (inner lst [])
in
outer ( [ tree ] )
;;
Basically, I keep a list of the nodes at each level. As I walk the list,
calling f on all non-leaf nodes, I create the list of the nodes at the
next level down. Note the List.rev trick I pull, to keep the nodes in the
"expected" order.
> 2) I think that this approach isn't flexible. What if I had a
> tree where I can move in other directions as well? Or if I were
> dealing with 5-generation grandchildren only?
A variant of the breadth-first walking I did above could easily generate a
list of all nodes on level 5. Dealing with multiple children is easy.
Assume that instead of the binary tree structure we had above, we had an
n'ary tree structure, like:
type 'a tree = Leaf
| Node of 'a * 'a tree list
Each node holds data and a list of 0 or more children it has. Depth first
search would then become:
let rec walk f tree =
let rec loop lst =
match lst with
[] -> ()
| h :: t -> walk f h ; loop t
in
match tree with
Leaf -> ()
| Node(data, children) ->
f data;
loop children
;;
A similiar modification works to do breadth first walking. More general
data structures aren't really trees anymore, they're graphs. But graph
walking works more or less the same way.
Hope this helps.
Brian
-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
next prev parent reply other threads:[~2003-05-09 15:12 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2003-05-09 9:56 Stalkern 2
2003-05-09 15:23 ` Brian Hurt [this message]
2003-05-12 12:57 ` John Carr
2003-05-12 13:35 ` Michal Moskal
2003-05-12 15:06 ` David Brown
2003-05-12 15:24 ` Xavier Leroy
2003-05-11 16:02 ` Xavier Leroy
2003-05-12 6:55 ` Stalkern 2
2003-05-12 10:14 ` Gérard Huet
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Pine.LNX.4.33.0305090959170.2037-100000@eagle.ancor.com \
--to=brian.hurt@qlogic.com \
--cc=caml-list@inria.fr \
--cc=stalkern2@tin.it \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox