File Coverage

blib/lib/Tree/Treap.pm
Criterion Covered Total %
statement 122 185 65.9
branch 42 74 56.7
condition 26 36 72.2
subroutine 27 41 65.8
pod 12 28 42.8
total 229 364 62.9


line stmt bran cond sub pod time code
1             package Tree::Treap;
2 1     1   33 use 5.006;
  1         3  
  1         49  
3 1     1   6 use strict;
  1         3  
  1         42  
4 1     1   5 use warnings;
  1         2  
  1         5377  
5             our $VERSION = '0.02';
6              
7             my %comp = ( str => sub {return $_[0] cmp $_[1]},
8             rstr => sub {return $_[1] cmp $_[0]},
9             num => sub {return $_[0] <=> $_[1]},
10             rnum => sub {return $_[1] <=> $_[0]},
11             );
12              
13             sub new {
14 3214     3214 1 3541 my $class = shift;
15 3214   66     6793 $class = ref($class)||$class;
16 3214         6375 my $self = bless {}, $class;
17 3214   50     6937 my $cmp = shift || "str";
18 3214 100       6096 if(ref($cmp) eq 'CODE'){
19 3190         6441 $self->{cmp} = $cmp;
20             } else {
21 24   33     83 $self->{cmp} = $comp{$cmp} || $comp{num};
22             }
23 3214         4403 $self->{priority} = -100;
24 3214         6019 $self->initialize(@_);
25 3214         6178 return $self;
26             }
27              
28 3214     3214 0 3356 sub initialize {}
29              
30             sub insert {
31 6471     6471 1 7198 my $self = shift;
32 6471         6651 my $key = shift;
33 6471         6700 my $data = shift;
34 6471 50       9598 $data = defined($data)? $data : $key;
35 6471   66     12907 my $priority = shift() || rand();
36            
37 6471 100       10463 if($self->_is_empty()) {
38 872         1937 $self->{priority} = $priority,
39             $self->{key} = $key;
40 872         1554 $self->{data} = $data;
41 872         1567 $self->{left} = $self->new($self->{cmp});
42 872         1861 $self->{right} = $self->new($self->{cmp});
43 872         1547 return $self;
44             }
45            
46 5599 100       12003 if($self->gt($key)){
    100          
47 4458         9386 $self->{right}->insert($key,$data,$priority);
48 4458 100       10926 if($self->{right}->{priority} > $self->{priority}){
49 811         1386 $self->_rotate_left();
50             }
51             }elsif($self->lt($key)){
52 921         2023 $self->{left}->insert($key,$data,$priority);
53 921 100       2246 if($self->{left}->{priority} > $self->{priority}){
54 225         370 $self->_rotate_right();
55             }
56              
57             }else{
58 220         398 $self->_delete_node();
59 220         658 $self->insert($key,$data,$priority);
60             }
61 5599         9226 return $self;
62             }
63              
64             sub delete {
65 0     0 1 0 my $self = shift;
66 0         0 my $key = shift;
67 0 0       0 return 0 unless $self = $self->_get_node($key);
68 0         0 $self->_delete_node();
69             }
70              
71              
72             sub _delete_node {
73 630     630   681 my $self = shift;
74 630 100       968 if($self->_is_leaf()) {
    100          
75 220         1435 %$self = (priority => -100, cmp => $self->{cmp});
76             } elsif ($self->{left}->{priority} > $self->{right}->{priority}) {
77 208         380 $self->_rotate_right();
78 208         516 $self->{right}->_delete_node();
79             } else {
80 202         347 $self->_rotate_left();
81 202         476 $self->{left}->_delete_node();
82             }
83             }
84              
85              
86             sub keys {
87 440     440 1 488 my $self = shift;
88 440 100       629 return () if $self -> _is_empty ();
89 217         559 ($self->{left}->keys(), $self->{key}, $self->{right}->keys());
90             }
91              
92             sub keys_post {
93 0     0 0 0 my $self = shift;
94 0 0       0 return () if $self->_is_empty();
95 0         0 ($self->{left}->keys_post(), $self->{right}->keys_post(),$self->{key});
96             }
97              
98             sub keys_pre {
99 0     0 0 0 my $self = shift;
100 0 0       0 return () if $self->_is_empty();
101 0         0 ($self->{key},$self->{left}->keys_pre(), $self->{right}->keys_pre());
102             }
103              
104             sub values {
105 0     0 0 0 my $self = shift;
106 0 0       0 return () if $self->_is_empty ();
107 0         0 ($self->{left}->values(), $self->{data}, $self->{right}->values());
108             }
109              
110             sub exists {
111 0     0 1 0 my $self = shift;
112 0         0 my $key = shift;
113 0 0       0 return 1 if $self->_get_node($key);
114 0         0 return;
115             }
116              
117             sub get_val {
118 1138     1138 1 2072 my $node = _get_node(@_);
119 1138 100       3965 return $node ? $node->{data} : undef;
120             }
121              
122              
123             sub _get_node {
124 1138     1138   1388 my $self = shift;
125 1138         1292 my $key = shift;
126 1138   100     2014 while(!$self->_is_empty() and $self->ne($key)){
127 6702 100       15871 $self = $self->{$self->lt($key)?"left":"right"}
128             }
129 1138 100       2358 return $self->_is_empty() ? 0 : $self;
130             }
131              
132              
133             sub range_keys {
134 35     35 1 44 my $self = shift;
135 35         84 my @keys = map{$_->{key}} $self->_range_nodes(@_);
  659         1183  
136 35         280 return @keys;
137             }
138             sub range_values {
139 0     0 1 0 my $self = shift;
140 0         0 my @values = map{$_->{data}} $self->_range_nodes(@_);
  0         0  
141 0         0 return @values;
142             }
143              
144             sub _range_nodes {
145 1370     1370   1465 my $self = shift;
146 1370         1521 my $low = shift;
147 1370         1330 my $high = shift;
148 1370         1225 my @return;
149 1370 100       2280 return () if $self->_is_empty ();
150              
151 690 100 100     1744 if (!defined $low || $self->lt($low)) {
152 666         1654 push @return, $self->{left}->_range_nodes($low, $high);
153             }
154              
155 690 100 100     3315 if ((!defined $low || $self->le($low)) &&
      100        
      66        
156             (!defined $high || $self->ge($high))) {
157 659         877 push @return, $self;
158             }
159              
160 690 100 100     2154 if (!defined $high || $self->gt($high)) {
161 669         1570 push @return, $self->{right}->_range_nodes($low, $high);
162             }
163              
164 690         2409 @return;
165             }
166              
167              
168             sub split {
169 0     0 0 0 my $self = shift;
170 0         0 my $key = shift;
171 0         0 $self->insert($key,undef,100);
172 0         0 my($T1, $T2) = ($self->{left},$self->{right});
173 0         0 $self->delete($key);
174 0         0 return ($T1,$T2);
175             }
176              
177             sub join {
178 0     0 0 0 my $self = shift;
179 0         0 my $T1 = shift;
180 0         0 my $T2 = shift;
181 0 0       0 if($T1->{cmp}->($T1->maximum(),$T2->minimum())>=0){
182 0         0 warn "Tree1 must be less than Tree2 in join()";
183 0         0 return;
184             }
185 0         0 my $cat = $self->new($self->{cmp});
186 0         0 ($cat->{left}, $cat->{right}) = ($T1,$T2);
187 0         0 $cat->_delete_node();
188 0         0 return $cat;
189             }
190              
191              
192             sub minimum {
193 20     20 1 45 my $self = shift;
194 20 50       47 return if $self->_is_empty();
195 20         51 while ( not $self->{left}->_is_empty()){
196 24         68 $self = $self->{left};
197             }
198 20         124 return $self->{key};
199             }
200             sub maximum {
201 10     10 1 12 my $self = shift;
202 10 50       18 return if $self->_is_empty();
203 10         26 while ( not $self->{right}->_is_empty()){
204 1         4 $self = $self->{right};
205             }
206 10         53 return $self->{key};
207             }
208              
209              
210             sub as_string {
211 0     0 0 0 my $self = shift;
212 0   0     0 my $mult = shift || 1;
213 0         0 my $indent = " " x $mult;
214 0 0       0 return "$indent+\n" if $self -> _is_empty ();
215 0         0 return $self->{right}->as_string($mult + 2) .
216             "$indent+-$self->{key}\n" .
217             $self->{left}->as_string($mult + 2);
218             }
219              
220              
221             sub max_height {
222 0     0 0 0 my $self = shift;
223 0   0     0 my $depth = shift||0;
224 0 0       0 return $depth - 1 if $self->_is_empty();
225 0         0 my $left = $self->{left}->max_height($depth + 1);
226 0         0 my $right = $self->{right}->max_height($depth + 1);
227 0 0       0 $depth = $left if $left > $depth;
228 0 0       0 $depth = $right if $right > $depth;
229 0         0 return $depth;
230             }
231              
232             sub successor {
233 5     5 1 8 my $self = shift;
234 5         6 my $key = shift;
235 5         10 my $ret = $self->_successor($key)->{key};
236 5         20 $ret;
237             }
238             sub _successor {
239 18     18   19 my $self = shift;
240 18         19 my $key = shift;
241 18 100       27 return $self if $self->_is_empty();
242 13 100       29 return $self->{right}->_successor($key) if $self->ge($key);
243 6         9 my $succ;
244 6 50       12 $succ = $self->{left}->_successor($key) if $self->lt($key);
245 6 100       15 $succ->_is_empty()? $self : $succ;
246             }
247              
248             sub predecessor {
249 0     0 1 0 my $self = shift;
250 0         0 my $key = shift;
251 0         0 my $ret = $self->_predecessor($key)->{key};
252 0         0 $ret;
253             }
254             sub _predecessor {
255 0     0   0 my $self = shift;
256 0         0 my $key = shift;
257 0 0       0 return $self if $self->_is_empty ();
258 0 0       0 return $self->{left}->_predecessor($key) if $self->le($key);
259 0         0 my $pred;
260 0 0       0 $pred = $self->{right}->_predecessor ($key) if $self->gt($key);
261 0 0       0 $pred->_is_empty () ? $self : $pred;
262             }
263              
264              
265             sub CMP {
266 22020     22020 0 22888 my $self = shift;
267 22020         26114 my $key = shift;
268 22020         26990 my $cmp = $self->{cmp};
269 22020         36275 $cmp->($key, $self->{key});
270             }
271              
272 7905     7905 0 13458 sub lt {shift->CMP(@_) < 0;}
273 56     56 0 98 sub le {shift->CMP(@_) <= 0;}
274 0     0 0 0 sub eq {shift->CMP(@_) == 0;}
275 7179     7179 0 13201 sub ne {shift->CMP(@_) != 0;}
276 647     647 0 1138 sub ge {shift->CMP(@_) >= 0;}
277 6233     6233 0 10231 sub gt {shift->CMP(@_) > 0;}
278 0     0 0 0 sub cmp {shift->CMP(@_)}
279              
280              
281             sub _clone_node {
282 2892     2892   2965 my $self = shift;
283 2892         2750 my $other = shift;
284 2892         17982 %$self = %$other;
285             }
286              
287             sub _rotate_left {
288 1013     1013   1152 my $self = shift;
289 1013         1840 my $tmp = $self->new($self->{cmp});
290 1013         2024 $tmp->_clone_node($self);
291 1013         3214 $self->_clone_node($self->{right});
292 1013         2606 $tmp->{right} = $self->{left};
293 1013         3156 $self->{left} = $tmp;
294            
295             }
296              
297             sub _rotate_right {
298 433     433   471 my $self = shift;
299 433         742 my $tmp = $self->new($self->{cmp});
300 433         803 $tmp->_clone_node($self);
301 433         1237 $self->_clone_node($self->{left});
302 433         1085 $tmp->{left} = $self->{right};
303 433         1195 $self->{right} = $tmp;
304             }
305              
306              
307 18317     18317   61863 sub _is_empty {!defined shift->{key}}
308              
309             sub _is_leaf {
310 630     630   613 my $self = shift;
311 630   100     1081 return $self->{left}->_is_empty() &&
312             $self->{right}->_is_empty();
313             }
314              
315              
316              
317             1;
318             __END__