annotate Tree/Interval/Node.pm @ 0:acc8d8bfeb9a

Uploaded
author jjohnson
date Wed, 08 Feb 2012 16:59:24 -0500
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
1 package Tree::Interval::Node;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
2
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
3 use strict;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
4 use Carp;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
5 use Tree::Interval::Node::Constants;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
6 use vars qw( $VERSION @EXPORT_OK );
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
7
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
8 require Exporter;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
9 *import = \&Exporter::import;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
10 @EXPORT_OK = qw[set_color color_of parent_of left_of right_of];
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
11
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
12 $VERSION = '0.1';
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
13
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
14 # key and interval is the same thing
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
15 my %attribute = (
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
16 key => _KEY,
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
17 val => _VAL,
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
18 color => _COLOR,
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
19 parent => _PARENT,
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
20 left => _LEFT,
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
21 right => _RIGHT,
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
22 max => _MAX,
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
23 interval => _INTERVAL,
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
24 );
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
25
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
26 #using an array instead of a hash for the node
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
27 sub _accessor {
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
28 my $index = shift;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
29 return sub {
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
30 my $self = shift;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
31 return undef unless $self;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
32 if (@_) {
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
33 $self->[$index] = shift;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
34 }
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
35 return $self->[$index];
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
36 };
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
37 }
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
38
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
39 while(my($at, $idx) = each %attribute) {
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
40 no strict 'refs';
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
41 *$at = _accessor($idx);
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
42 }
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
43
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
44 sub new {
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
45 my $class = shift;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
46 my $obj = [];
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
47
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
48 if (@_) {
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
49 $obj->[_KEY] = $obj->[_INTERVAL] = shift;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
50 $obj->[_VAL] = shift;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
51 }
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
52 return bless $obj, $class;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
53 }
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
54
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
55 sub left_most {
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
56 my $self = shift;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
57 while ($self->[_LEFT]) {
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
58 $self = $self->[_LEFT];
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
59 }
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
60 return $self;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
61 }
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
62
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
63 sub right_most {
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
64 my $self = shift;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
65 while ($self->[_RIGHT]) {
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
66 $self = $self->[_RIGHT];
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
67 }
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
68 return $self;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
69 }
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
70
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
71 #find left_most leaf
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
72 sub leaf {
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
73 my $self = shift;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
74 while (my $any_child = $self->[_LEFT] || $self->[_RIGHT]) {
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
75 $self = $any_child;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
76 }
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
77 return $self;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
78 }
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
79
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
80 sub successor {
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
81 my $self = shift;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
82 if ($self->[_RIGHT]) {
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
83 return $self->[_RIGHT]->left_most;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
84 }
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
85 my $parent = $self->[_PARENT];
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
86 while ($parent && $parent->[_RIGHT] && $self == $parent->[_RIGHT]) {
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
87 $self = $parent;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
88 $parent = $parent->[_PARENT];
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
89 }
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
90 return $parent;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
91 }
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
92
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
93 sub predecessor {
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
94 my $self = shift;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
95 if ($self->[_LEFT]) {
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
96 return $self->[_LEFT]->right_most;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
97 }
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
98 my $parent = $self->[_PARENT];
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
99 while ($parent && $parent->[_LEFT] && $self == $parent->[_LEFT]) {
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
100 $self = $parent;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
101 $parent = $parent->[_PARENT];
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
102 }
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
103 return $parent;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
104 }
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
105
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
106 sub as_lol {
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
107 my $self = shift;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
108 my $node = shift || $self;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
109 my $aref;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
110 push @$aref,
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
111 $node->[_LEFT]
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
112 ? $self->as_lol($node->[_LEFT])
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
113 : '*';
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
114 push @$aref,
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
115 $node->[_RIGHT]
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
116 ? $self->as_lol($node->[_RIGHT])
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
117 : '*';
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
118 my $color = ($node->[_COLOR] == RED ? 'R' : 'B');
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
119 no warnings 'uninitialized';
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
120 push @$aref, "$color:[$node->[_KEY][0],$node->[_KEY][1]]:$node->[_MAX]";
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
121 return $aref;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
122 }
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
123
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
124 sub strip {
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
125 my $self = shift;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
126 my $callback = shift;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
127
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
128 my $x = $self;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
129 while($x) {
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
130 my $leaf = $x->leaf;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
131 $x = $leaf->[_PARENT];
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
132
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
133 # detach $leaf from the (sub)tree
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
134 no warnings "uninitialized";
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
135 if($leaf == $x->[_LEFT]) {
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
136 undef $x->[_LEFT];
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
137 }
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
138 else {
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
139 undef $x->[_RIGHT];
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
140 }
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
141 undef $leaf->[_PARENT];
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
142 if($callback) {
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
143 $callback->($leaf);
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
144 }
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
145
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
146 if(!$x->[_LEFT] && !$x->[_RIGHT]) {
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
147 $x = $x->[_PARENT];
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
148 }
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
149 }
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
150 }
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
151
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
152 sub DESTROY { $_[0]->strip; }
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
153
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
154 # Null aware accessors to assist with rebalancings during insertion and deletion
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
155 #
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
156 # A weird case of Java to the rescue!
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
157 # These are inspired by http://www.javaresearch.org/source/jdk142/java/util/TreeMap.java.html
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
158 # which was found via http://en.wikipedia.org/wiki/Red-black_tree#Implementations
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
159
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
160 # do wen need it? as we have accessors already
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
161 sub set_color {
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
162 my ($node, $color) = @_;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
163 if($node) {
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
164 $node->[_COLOR] = $color;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
165 }
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
166 }
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
167
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
168 sub color_of {
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
169 $_[0] ? $_[0]->[_COLOR] : BLACK;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
170 }
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
171
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
172 sub parent_of {
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
173 $_[0] ? $_[0]->[_PARENT] : undef;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
174 }
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
175
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
176 sub left_of {
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
177 $_[0] ? $_[0]->[_LEFT] : undef;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
178 }
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
179
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
180 sub right_of {
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
181 $_[0] ? $_[0]->[_RIGHT] : undef;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
182 }
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
183
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
184 sub _overlap {
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
185 my ($a, $b) = @_;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
186 return 1 if($a->[0] <= $b->[1] && $a->[1] >= $b->[0]);
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
187 return undef;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
188 }
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
189
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
190 sub intersect {
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
191 my $x = shift;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
192 my $interval = shift;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
193 return if(!$x);
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
194 # print $x->val->name, "\t", $x->key->[0], "\t", $x->key->[1], "\n";
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
195 my @rtn;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
196 if(_overlap($x->interval, $interval)) {
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
197 push @rtn, $x;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
198 }
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
199 # my $y = $x->parent;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
200 if($x->left && $x->left->max >= $interval->[0] ) { # && (!$y || _overlap($interval, [$y->interval->[0], $x->left->max]))) {
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
201 push @rtn, $x->left->intersect($interval);
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
202 }
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
203 push @rtn, $x->right->intersect($interval) if($x->right && _overlap($interval, [$x->interval->[0], $x->right->max]));
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
204 return @rtn;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
205 }
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
206
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
207 1;
acc8d8bfeb9a Uploaded
jjohnson
parents:
diff changeset
208