Circular Trees
Examples where trees (the instances of tree values, not the data type definition) are self-dependent, recursive, or circular.
N-Queens
e.g. N=5
|
"The well known n-queens problem is to place n queens
on an n×n chess board so that no two queens threaten
each other. Each queen must be on a separate row,
column and diagonal and this property is an invariant
that must be maintained as partial solutions are extended.
The fastest imperative solutions [Rohl 1983] are based on
permutation generators. A board is represented by
the permutation of rows that the queens on the columns occupy.
This representation automatically ensures the separate row and column
parts of the invariant. Here we observe that a partial solution
abcde can be extended to a partial solution abcdeX if and
only if bcdeX is also a partial solution and a and X are
on separate diagonals and rows. By using shadows*, X need
only be tested against a's diagonals as the results of
the other diagonal tests against other queens are already encoded in the
shadow tree and do not need to be repeated.[...]" -
(Allison 1993)
[*]
The shadow of the partial solution abcde
is bcde which is also a partial solution and
must be in the tree (and closer to the root),
if abcde is in the tree.
| ------------------------------------ 1 2 3 4 5 | | | | | ------- ----- ----- ----- ------- 3 4 5 4 5 1 5 1 2 1 2 3 | . . . . . | . . . | . etc | . . . --- | 5 . . 1 2 4 | . | . 2 4 . | . 4 . |
Partial tree of solutions, N=5. |
module Queens (module Queens) where -- NB. element subtree siblings! This is an n-ary tree data Tree a = Node a (Tree a) (Tree a) | Empty paths depth t = -- paths from the root of t to given depth let across d ancestors Empty rest = rest across d ancestors (Node e l r) rest = down d (e:ancestors) l (across d ancestors r rest) down d ancestors t rest = if d >= depth then ancestors:rest else across (d+1) ancestors t rest in across 1 [] t [] member x [] = False member x (y:ys) = x==y || member x ys build n = -- build tree of solutions let t = toplevel 1 -- note circularity t ~ toplevel -- L.A. toplevel m = -- note the use of t below if m > n then Empty else Node m (f 1 m t) (toplevel (m+1)) f col banned Empty = Empty -- shadowless f col banned (Node a subtree sibs) = let others = f col banned sibs in if member banned [a, a+col, a-col] then others else Node a (f (col+1) banned subtree) others in t queens n = paths n (build n)
-- Queens.hs --
More
- L. Allison. Applications of Recursively Defined Data Structures. Australian Computer Journal 25(1) pp14-20 1993.