Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

help! red-black binary tree problem

by frustrated_intern (Initiate)
on Jul 23, 2005 at 00:41 UTC ( [id://477400]=perlquestion: print w/replies, xml ) Need Help??

frustrated_intern has asked for the wisdom of the Perl Monks concerning the following question:

hi, i'm a relatively new Perl programmer -- i normally code in either C,C++ or Java. i'm working as an intern this summmer, and working on a red-black binary tree implementation problem. i'm pretty sure it's a Perl syntax problem. Not blessed w/ vast knowledge about the language, it would be great if i could get some help!

here's the situation:

after i delete a node, and modify the necessary parent/child pointers, my tree becomes corrupted, and several nodes near the region where a node was deleted as a result of the delete function call lose their parent pointers.

at the end of my delete function (displayed below) i return my "successor" node (the smallest node larger than the node being deleted). if the deleted node doesn't have a left or right child, this "successor" node is the node itself. in this situation, once i exit the delete function, i lose information about the parent pointers for the nodes to the left or right of the deleted node (which are moved up, and become the children of the deleted node's parent). instead, their parent pointers are set to undefined.

here's the interesting part: at the end of my delete function, i return the successor node (referred to as $curr). if i have a receiver for the returned $curr node outside of my program, everything works fine. it's just that when there is no receiver (hence $curr is garbage collected) that the tree becomes corrupted. this is strange, because the new pointers set after the node is deleted don't intersect with the returned node.

any hints on how to fix this? both my mentor and i are officially stumped. thanks!

- frustrated_intern

code shown below:

sub RBDelete{ my($self, $key) = @_; if($self->isEmpty){ #empty tree die "Illegal Operation 4: Cannot delete without first insertin +g."; } my $node = $self->RBSearch($key); #find node in tree if(!(defined $node)){ #non-inserted node die "Illegal Operation 5: Cannot delete node without first ins +erting it."; } if($node->equals($self->{_root}) == 1) && $node->isLeaf){ $self->{_root} = ref($node); return; } my $curr; my $temp; if(!($node->hasLeft) || !($node->hasRight)){ $curr = $node; }else{ $curr = $node->mySuccessor; #successor node -- } if($curr->hasLeft){ $temp = $curr->getLeft; }elsif($curr->hasRight){ $temp = $curr->getRight; }else{ $temp = $self->{_sentinel_node}; #set up sentinel node as "dum +my node" } my $currP = $curr->getParent; if($node->isRoot){ $self->{_root}->markRoot(0); $self->{_root} = $temp; $temp->markRoot(1); }elsif($curr->equals($curr->getParent->getLeft)){ #curr is left ch +ild if(defined $temp->getNodeKey){ #set temp to cur's parent $currP->setLeft($temp); }else{ $currP->removeLeft; } }else{ if(defined $temp->getNodeKey){ #curr is right child $currP->mySetRight($temp); #set temp as curr's parent's r +ight child }else{ $currP->removeRight; } } my $currColor = $curr->getNodeColor; if($curr->equals($node) == 0){ #curr and node distinct nodes -- sh +ift curr up to node's position my $nodeRight = $node->getRight; my $nodeLeft = $node->getLeft; $node->{_right} = undef; $node->{_left} = undef; if($node->isRoot){ $self->{_root}->markRoot(0); $curr->markRoot(1); $self->{_root} = $curr; }else{ if($node->equals($node->getParent->getLeft)){ $node->getParent->setLeft($curr); }else{ $node->getParent->setRight($curr); } } if(defined $nodeRight){ $curr->setRight($nodeRight); } if(defined $nodeLeft){ $curr->setLeft($nodeLeft); } $curr->setNodeColor($node->getNodeColor); } if($currColor == 0){ $self->RBDeleteFix($temp); } return $curr; }

Edit g0n: closed b tag after "here's the situation"

Replies are listed 'Best First'.
Re: help! red-black binary tree problem
by Ovid (Cardinal) on Jul 23, 2005 at 01:45 UTC

    Unfortunately, due to its age and lack of tests, I'm hard-pressed to vouch for it, but you might find Tree::RedBlack of use.

    Cheers,
    Ovid

    New address of my CGI Course.

      The docs for delete point out "WARNING!!! THIS STILL HAS BUGS!!!".
Re: help! red-black binary tree problem
by Daedalus207 (Novice) on Jul 23, 2005 at 07:36 UTC
    "here's the interesting part: at the end of my delete function, i return the successor node (referred to as $curr). if i have a receiver for the returned $curr node outside of my program, everything works fine."


    Within RBDelete, you're telling $node's parent to point to $curr. $curr is local to RBDelete. If you don't store the-node-formerly-known-as-$curr outside the scope of RBDelete by capturing the return value, the parent of your deleted node will be pointing to undef.

      I realize that the problem has to do with scoping -- however, the problem doesn't have to do with the parent of the deleted node pointing to undef. Each node has three pointers: pointer to parent, and pointer to children(left/right).

      If I'm dealing with the case that both $node and $curr point to the same RBNode (see code in previous post). The strange thing that happens is that the deleted node's children's parent pointers end up pointing to undef, even though $curr's parent's left and right pointers point to the proper nodes. I find this baffling. Any ideas as to how to fix the problem?

      The catch with my RedBlack binary tree implementation is that I can't capture any return balue. Any ideas as to how to fix my code w/o having to capture any return value? The code works perfectly fine when $node and $curr point to distinct nodes. Thanks.

You probably want a hash.
by schwern (Scribe) on Jul 23, 2005 at 19:55 UTC

    One of my first perl modules ever was an attempt at a family of binary search tree modules. The few programming classes I took taught a lot about trees and they seemed really neat, especially splay trees which could self-optimize.

    I discovered this: The performance stinks. Unless you're dealing with a bazillion records, just use a hash. Even having to sort a hash each time the performance will blow a tree written in Perl out of the water. One of those cases where C is significant in calculating algorithm efficiency.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://477400]
Approved by jdalbec
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others meditating upon the Monastery: (3)
As of 2024-04-19 01:11 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found