Next: bst bnodes, Up: bst [Index]
The binary search trees are tree structures in which every node has at most two children. Every node is associated to a “sort key”: a value that can be used to establish an ordering among the nodes. The node insertion and node removal operations are implemented in such a way that:
Here is an example of binary search tree, with nodes in the correct order:
5-------10----12 | | | 1--3--4 7--9 11 | | | 2 6 8
the root node has sort key ‘5’; the left child of the root has sort key ‘1’; the right child of the root has sort key ‘10’. Let’s take ‘10’ as example: every node in its left subtree has key less than ‘10’; every node in its right subtree has key greater than, or equal to, ‘10’. This is a general property of binary search trees.
The library (vicare containers binary-search-trees)
is the core
library for binary search tree implementation; it implements trees in
such a way that:
#f
.
<binary-node>
or
a subtype of this type.
<binary-node>
has 3 fields: parent
,
left
, right
. The value of these fields can be #f
or
an instance of <binary-node>
.
parent
field of a node is set to #f
: it means that
node is the root of a tree.
All the functions acting on instances of <binary-node>
are
meant to be usable on trees implementing any node balancing strategy;
they only expect the binary tree to be a binary search tree as defined
above. The core library only implements unbalanced binary search trees,
in which nodes have the type <unbalanced-binary-node>
. The
type hierarchy is:
(define-record-type <binary-node> ---) (define-record-type <unbalanced-binary-node> (parent <binary-node>) ---)
By themselves, these types have no sort key; to associate a sort key with a node instance we need to subtype them. The following is an example of binary search tree of fixnums:
(import (vicare) (vicare containers binary-search-trees)) (define-record-type <fixnum-node> (parent <unbalanced-binary-node>) (fields (immutable sort-key)) (protocol (lambda (make-unbalanced-binary-node) (case-lambda* (() ((make-unbalanced-binary-node #f #f) (void))) ((key) ((make-unbalanced-binary-node #f #f) key)) (({key fixnum?} {left false-or-unbalanced-binary-node?} {right false-or-unbalanced-binary-node?}) ((make-unbalanced-binary-node left right) key))))) #| end of DEFINE-RECORD-TYPE |# ) (define (key< new old) (fx<? (<fixnum-node>-sort-key new) (<fixnum-node>-sort-key old))) (define (make-comparison-proc target-key) (lambda (node) (let ((key (<fixnum-node>-sort-key node))) (cond ((fx=? target-key key) 0) ((fx<? target-key key) -1) (else +1)))))
we can build a tree from a list and then search for a node as follows:
(define (tree . key*) (fold-left (lambda (root key) (unbalanced-tree-insert! root key< (make-<fixnum-node> key))) #f key*)) ;; 5-------10----12 ;; | | | ;; 1--3--4 7--9 11 ;; | | | ;; 2 6 8 (define root (tree 5 1 3 2 4 10 7 12 6 9 8 11)) (define node (binary-tree-find root (make-comparison-proc 8)))
we can perform a forwards in–order iteration as follows:
(binary-tree-fold-in-order-forwards (lambda (knil node) (cons (<fixnum-node>-sort-key node) knil)) '() root)) ⇒ (12 11 10 9 8 7 6 5 4 3 2 1)
in the result of this operation: the sort key in the first node from the search is the last item in the list.
Next: bst bnodes, Up: bst [Index]