Re: Depth First Search traversal of this list
- From: Kaz Kylheku <kkylheku@xxxxxxxxx>
- Date: Thu, 11 Sep 2008 23:00:08 +0000 (UTC)
On 2008-09-10, crashoverride111@xxxxxxxxx <crashoverride111@xxxxxxxxx> wrote:
Hello,
I am trying to traverse the list (A (B (D E) C)) in a way that the
print output should be in the following order D, E, B, C, A aka depth
first traversal.
This isn't depth-first traversal.
Depth first means: A B D E C, in other words, the left-to-right order in
which the nodes appear.
Breadth first means: A B C D E. The tree is traversed down to level N,
before proceeding to level N + 1.
What you are asking for is to visit level N + 1 before visiting level N.
This is not what is generally understood, in computer science, as
depth first.
This is almost like the output of a breadth-first traversal in reverse,
except that you still want to process each level left-to-right.
So we can start by coding a breadth-first traversal. This algorithm
works by iterating over the items at one level in the tree. Atoms
at the current level are visited in left-to-right order. Subtrees (i.e. conses)
are deferred into a queue, which is processed after the atoms are visited.
We append the list together, so for instance if we are processing
(A (B C) D (E F)) the algorithm will visit A, append (B C) to the queue, then
visit D, and append (E F) to the queue, so the queue holds (B C E F).
It will then recurse over the queue, visiting B C E F.
(defun breadth-first-map (function tree)
(loop for item in tree
if (consp item)
append item into queue
else
do (funcall function item)
finally
(unless (null queue)
(breadth-first-map function queue))))
Test cases:
(breadth-first-map #'print '(1 2 (3 (9 10) 4) 5 (6 7)))
-> NIL
[output]
1
2
5
3
4
6
7
9
10
[/output]
(breadth-first-map #'print '(A (B (D E) C)))
-> NIL
[output]
A
B
C
D
E
[/output]
So that is breadth-first traversal. What you are looking for is a traversal
which visits the levels in the reverse order: lower levels first. At each
level, it still visits the atoms in the left-to-right order.
To visit the lower level first, we cannot process the current level items
immediately as we see them. We must collect them into a list.
And we must still maintain a queue for visiting the next lower depth.
After collecting both the queue and current level items, we do the recursion to
the next depth first, and then map the saved current level items through the
function to visit them:
(defun breadth-first-map-bottom-up (function tree)
(loop for item in tree
if (consp item)
append item into queue
else
collect item into current-level-items
finally
;; recurse to lower depths first---
;; ---not to be confused with ``depth-first traversal''!!!
(unless (null queue)
(breadth-first-map-bottom-up function queue))
;; then process items at this level
(mapc function current-level-items)))
(breadth-first-map-right-left-bottom-up #'print '(A (B (D E) C)))
[output]
D
E
B
C
A
[/output]
So there is your so-called ``depth first'' traversal.
It doesn't appear to be a particularly useful invention.
One last note. Notice that the original breadth-first traversal is tail
recursive; it can be trivially rewritten as a loop. The last thing it does is
call itself, and doesn't do anything with the return value, other
than pass it up.
This means we can replace the recursive call by assigning to the parameters and
looping backwards. The null queue test which terminates the recursion becomes a
termination test for our loop. For the sake of variety, let's use DO, and move
the termination test into its termination clause:
(defun breadth-first-map (function tree)
(do () ((null tree)) ;; loop until tree is null
(loop for item in tree
if (consp item)
append item into queue
else
do (funcall function item)
finally
;; process next level by treating the
;; queue as the tree
(setf tree queue))))
Homework for you: is the bottom-up version of the traversal tail recursive?
Can we easily rewrite it to use iteration?
.
- Follow-Ups:
- Re: Depth First Search traversal of this list
- From: Alex Mizrahi
- Re: Depth First Search traversal of this list
- References:
- Depth First Search traversal of this list
- From: crashoverride111
- Depth First Search traversal of this list
- Prev by Date: Re: Depth First Search traversal of this list
- Next by Date: Re: What do you LISPers think of Haskell?
- Previous by thread: Re: Depth First Search traversal of this list
- Next by thread: Re: Depth First Search traversal of this list
- Index(es):
Relevant Pages
|