| Filename | /Users/ap13/perl5/lib/perl5/Graph/UnionFind.pm |
| Statements | Executed 3 statements in 484µs |
| Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
|---|---|---|---|---|---|
| 1 | 1 | 1 | 12µs | 25µs | Graph::UnionFind::BEGIN@3 |
| 0 | 0 | 0 | 0s | 0s | Graph::UnionFind::_parent |
| 0 | 0 | 0 | 0s | 0s | Graph::UnionFind::_rank |
| 0 | 0 | 0 | 0s | 0s | Graph::UnionFind::add |
| 0 | 0 | 0 | 0s | 0s | Graph::UnionFind::find |
| 0 | 0 | 0 | 0s | 0s | Graph::UnionFind::has |
| 0 | 0 | 0 | 0s | 0s | Graph::UnionFind::new |
| 0 | 0 | 0 | 0s | 0s | Graph::UnionFind::same |
| 0 | 0 | 0 | 0s | 0s | Graph::UnionFind::union |
| Line | State ments |
Time on line |
Calls | Time in subs |
Code |
|---|---|---|---|---|---|
| 1 | package Graph::UnionFind; | ||||
| 2 | |||||
| 3 | 2 | 482µs | 2 | 38µs | # spent 25µs (12+13) within Graph::UnionFind::BEGIN@3 which was called:
# once (12µs+13µs) by Graph::BEGIN@31 at line 3 # spent 25µs making 1 call to Graph::UnionFind::BEGIN@3
# spent 13µs making 1 call to strict::import |
| 4 | |||||
| 5 | sub _PARENT () { 0 } | ||||
| 6 | sub _RANK () { 1 } | ||||
| 7 | |||||
| 8 | sub new { | ||||
| 9 | my $class = shift; | ||||
| 10 | bless { }, $class; | ||||
| 11 | } | ||||
| 12 | |||||
| 13 | sub add { | ||||
| 14 | my ($self, $elem) = @_; | ||||
| 15 | $self->{ $elem } = [ $elem, 0 ] unless defined $self->{$elem}; | ||||
| 16 | } | ||||
| 17 | |||||
| 18 | sub has { | ||||
| 19 | my ($self, $elem) = @_; | ||||
| 20 | exists $self->{ $elem }; | ||||
| 21 | } | ||||
| 22 | |||||
| 23 | sub _parent { | ||||
| 24 | return undef unless defined $_[1]; | ||||
| 25 | if (@_ == 2) { | ||||
| 26 | exists $_[0]->{ $_[ 1 ] } ? $_[0]->{ $_[1] }->[ _PARENT ] : undef; | ||||
| 27 | } elsif (@_ == 3) { | ||||
| 28 | $_[0]->{ $_[1] }->[ _PARENT ] = $_[2]; | ||||
| 29 | } else { | ||||
| 30 | require Carp; | ||||
| 31 | Carp::croak(__PACKAGE__ . "::_parent: bad arity"); | ||||
| 32 | } | ||||
| 33 | } | ||||
| 34 | |||||
| 35 | sub _rank { | ||||
| 36 | return unless defined $_[1]; | ||||
| 37 | if (@_ == 2) { | ||||
| 38 | exists $_[0]->{ $_[1] } ? $_[0]->{ $_[1] }->[ _RANK ] : undef; | ||||
| 39 | } elsif (@_ == 3) { | ||||
| 40 | $_[0]->{ $_[1] }->[ _RANK ] = $_[2]; | ||||
| 41 | } else { | ||||
| 42 | require Carp; | ||||
| 43 | Carp::croak(__PACKAGE__ . "::_rank: bad arity"); | ||||
| 44 | } | ||||
| 45 | } | ||||
| 46 | |||||
| 47 | sub find { | ||||
| 48 | my ($self, $x) = @_; | ||||
| 49 | my $px = $self->_parent( $x ); | ||||
| 50 | return unless defined $px; | ||||
| 51 | $self->_parent( $x, $self->find( $px ) ) if $px ne $x; | ||||
| 52 | $self->_parent( $x ); | ||||
| 53 | } | ||||
| 54 | |||||
| 55 | sub union { | ||||
| 56 | my ($self, $x, $y) = @_; | ||||
| 57 | $self->add($x) unless $self->has($x); | ||||
| 58 | $self->add($y) unless $self->has($y); | ||||
| 59 | my $px = $self->find( $x ); | ||||
| 60 | my $py = $self->find( $y ); | ||||
| 61 | return if $px eq $py; | ||||
| 62 | my $rx = $self->_rank( $px ); | ||||
| 63 | my $ry = $self->_rank( $py ); | ||||
| 64 | # print "union($x, $y): px = $px, py = $py, rx = $rx, ry = $ry\n"; | ||||
| 65 | if ( $rx > $ry ) { | ||||
| 66 | $self->_parent( $py, $px ); | ||||
| 67 | } else { | ||||
| 68 | $self->_parent( $px, $py ); | ||||
| 69 | $self->_rank( $py, $ry + 1 ) if $rx == $ry; | ||||
| 70 | } | ||||
| 71 | } | ||||
| 72 | |||||
| 73 | sub same { | ||||
| 74 | my ($uf, $u, $v) = @_; | ||||
| 75 | my $fu = $uf->find($u); | ||||
| 76 | return undef unless defined $fu; | ||||
| 77 | my $fv = $uf->find($v); | ||||
| 78 | return undef unless defined $fv; | ||||
| 79 | $fu eq $fv; | ||||
| 80 | } | ||||
| 81 | |||||
| 82 | 1 | 2µs | 1; | ||
| 83 | __END__ |