File Coverage

blib/lib/Tree/RedBlack/Node.pm
Criterion Covered Total %
statement 47 56 83.9
branch 19 22 86.3
condition 0 3 0.0
subroutine 11 12 91.6
pod 9 10 90.0
total 86 103 83.5


line stmt bran cond sub pod time code
1             package Tree::RedBlack::Node;
2              
3 1     1   5 use strict;
  1         1  
  1         1472  
4              
5             =head1 NAME
6              
7             Tree::RedBlack::Node - Node class for Perl implementation of Red/Black tree
8              
9             =head1 SYNOPSIS
10              
11             use Tree::RedBlack;
12             my $t = new Tree::RedBlack;
13             $t->insert(3, 'dog');
14             my $node = $t->node(3);
15             $animal = $node->val;
16              
17             =head1 DESCRIPTION
18              
19             A Tree::RedBlack::Node object supports the following methods:
20              
21             =over 4
22              
23             =item key ()
24              
25             Key of the node. This is what the nodes are sorted by in the tree.
26              
27             =item val ($)
28              
29             Value of the node. Can be any perl scalar, so it could be a hash-ref,
30             f'rinstance. This can be set directly.
31              
32             =item color ()
33              
34             Color of the node. 1 for "red", 0 or undef for "black".
35              
36             =item parent ()
37              
38             Parent node of this one. Returns undef for root node.
39              
40             =item left ()
41              
42             Left child node of this one. Returns undef for leaf nodes.
43              
44             =item right ()
45              
46             Right child node of this one. Returns undef for leaf nodes.
47              
48             =item min ()
49              
50             Returns the node with the minimal key starting from this node.
51              
52             =item max ()
53              
54             Returns the node with the maximal key starting from this node.
55              
56             =item successor ()
57              
58             Returns the node with the smallest key larger than this node's key, or this
59             node if it is the node with the maximal key.
60              
61             =item predecessor ()
62              
63             Similar to successor. WARNING: NOT YET IMPLEMENTED!!
64              
65             =back
66              
67             You can use these methods to write utility routines for actions on red/black
68             trees. For instance, here's a routine which writes a tree out to disk, putting
69             the byte offsets of the left and right child records in the record for each
70             node.
71              
72             sub dump {
73             my($node, $fh) = @_;
74             my($left, $right);
75             my $pos = tell $fh;
76             print $fh $node->color ? 'R' : 'B';
77             seek($fh, 8, 1);
78             print $fh $node->val;
79             if ($node->left) {
80             $left = dump($node->left,$fh);
81             }
82             if ($node->right) {
83             $right = dump($node->right,$fh);
84             }
85             my $end = tell $fh;
86             seek($fh, $pos+1, 0);
87             print $fh pack('NN', $left, $right);
88             seek($fh, $end, 0);
89             $pos;
90             }
91              
92             You would call it like this:
93              
94             my $t = new Tree::RedBlack;
95             ...
96             open(FILE, ">tree.dump");
97             dump($t->root,\*FILE);
98             close FILE;
99              
100             As another example, here's a simple routine to print a human-readable dump of
101             the tree:
102              
103             sub pretty_print {
104             my($node, $fh, $lvl) = @_;
105             if ($node->right) {
106             pretty_print($node->right, $fh, $lvl+1);
107             }
108             print $fh ' 'x($lvl*3),'[', $node->color ? 'R' : 'B', ']', $node->key, "\n";
109             if ($node->left) {
110             pretty_print($this->left, $fh, $lvl+1);
111             }
112             }
113              
114             A cleaner way of doing this kind of thing is probably to allow sub-classing of
115             Tree::RedBlack::Node, and then allow the Tree::RedBlack constructor to take an
116             argument saying what class of node it should be made up out of. Hmmm...
117              
118             =head1 AUTHOR
119              
120             Benjamin Holzman
121              
122             =head1 SEE ALSO
123              
124             Tree::RedBlack
125              
126             =cut
127              
128             sub new {
129 9     9 0 11 my $type = shift;
130 9         15 my $this = {};
131 9 100       17 if (ref $type) {
132 5         9 $this->{'parent'} = $type;
133 5         6 $type = ref $type;
134             }
135 9 100       20 if (@_) {
136 7         32 @$this{'key','val'} = @_;
137             }
138 9         38 return bless $this, $type;
139             }
140              
141             sub DESTROY {
142 16 100   16   72 if ($_[0]->{'left'}) {
143 3         10 (delete $_[0]->{'left'})->DESTROY;
144             }
145 16 100       32 if ($_[0]->{'right'}) {
146 2         6 (delete $_[0]->{'right'})->DESTROY;
147             }
148 16         142 delete $_[0]->{'parent'};
149             }
150              
151             sub key {
152 51     51 1 58 my $this = shift;
153 51 50       79 if (@_) {
154 0         0 $this->{'key'} = shift;
155             }
156 51         184 $this->{'key'};
157             }
158              
159             sub val {
160 12     12 1 12 my $this = shift;
161 12 100       25 if (@_) {
162 1         2 $this->{'val'} = shift;
163             }
164 12         47 $this->{'val'};
165             }
166              
167             sub color {
168 39     39 1 44 my $this = shift;
169 39 100       120 if (@_) {
170 25         41 $this->{'color'} = shift;
171             }
172 39         116 $this->{'color'};
173             }
174              
175             sub left {
176 47     47 1 66 my $this = shift;
177 47 100       90 if (@_) {
178 8         10 $this->{'left'} = shift;
179             }
180 47         159 $this->{'left'};
181             }
182              
183             sub right {
184 39     39 1 42 my $this = shift;
185 39 100       70 if (@_) {
186 8         10 $this->{'right'} = shift;
187             }
188 39         120 $this->{'right'};
189             }
190              
191             sub parent {
192 75     75 1 88 my $this = shift;
193 75 100       126 if (@_) {
194 10         17 $this->{'parent'} = shift;
195             }
196 75         228 $this->{'parent'};
197             }
198              
199             sub successor {
200 0     0 1 0 my $this = shift;
201 0 0       0 if ($this->{'right'}) {
202 0         0 return $this->{'right'}->min;
203             }
204 0         0 my $parent = $this->{'parent'};
205 0   0     0 while ($parent && $this == $parent->{'right'}) {
206 0         0 $this = $parent;
207 0         0 $parent = $parent->{'parent'};
208             }
209 0         0 $parent;
210             }
211              
212             sub min {
213 4     4 1 6 my $this = shift;
214 4         8 while ($this->{'left'}) {
215 1         4 $this = $this->{'left'};
216             }
217 4         13 $this;
218             }
219              
220             sub max {
221 2     2 1 3 my $this = shift;
222 2         6 while ($this->{'right'}) {
223 1         5 $this = $this->{'right'};
224             }
225 2         7 $this;
226             }
227              
228             1;