Monday, November 26, 2007

PHP Balanced tree - Add element/node

This script add element to the tree if it doesn't exist, if exists just increment it counter.


function search_btree( $value, $ptr, $higher, $ptr0 = 0,$node = 'left' )
{
global $tree;
static
$first_run = 1,
$higher,
$beginning;

if( !$tree[$ptr]['value'] )// insertion
{
if( !$first_run )// create new element in the tree array - $tree
{
$tree[] = array();
$ptr = count($tree)-1;

$tree[$ptr0][$node] = $ptr;// put current node in parent's left or right node

}else{// $tree[0] is already create so we just use is
$first_run--;
$beginning = $ptr;
}
$higher = true;

$tree[$ptr]['value'] = $value;
$tree[$ptr]['left'] = null;
$tree[$ptr]['right'] = null;
$tree[$ptr]['bal'] = 0;
$tree[$ptr]['count'] = 1;

}
else
{
if( $value < $tree[$ptr]['value'] )
{
search_btree( $value, $tree[$ptr]['left'], $higher, $ptr );
if( $higher )
{
switch( $tree[$ptr]['bal'] )
{
case 1:
$tree[$ptr]['bal'] = 0;
$higher = false;
break;
case 0:
$tree[$ptr]['bal'] = -1;
break;
case -1:
$ptr1 = $tree[$ptr]['left'];
if( $tree[$ptr1]['bal'] == -1) // individualli flip LL
{

$tree[$ptr]['left'] = $tree[$ptr1]['right'];
$tree[$ptr1]['right'] = $ptr;
$tree[$ptr]['bal'] = 0;


if( $ptr == $beginning )
$beginning = $ptr1;
// replaces $ptr with $ptr1 in parent left or right node
replace_pointer_link( $ptr, $ptr1 );
$ptr = $ptr1;
}
else
{
$ptr2 = $tree[$ptr1]['right'];

$tree[$ptr1]['right'] = $tree[$ptr2]['left'];
$tree[$ptr2]['left'] = $ptr1;

$tree[$ptr]['left'] = $tree[$ptr2]['right'];
$tree[$ptr2]['right'] = $ptr;

if( $tree[$ptr2]['bal'] == -1 )
$tree[$ptr]['bal'] = 1;
else
$tree[$ptr]['bal'] = 0;

if( $tree[$ptr2]['bal'] == 1 )
$tree[$ptr1]['bal'] = -1;
else
$tree[$ptr1]['bal'] = 0;

if( $ptr == $beginning )
$beginning = $ptr2;
replace_pointer_link( $ptr, $ptr2 );
$ptr = $ptr2;

}
$tree[$ptr]['bal'] = 0;
$higher = false;
break;
}
}
}
else if( $value > $tree[$ptr]['value'] )
{
search_btree( $value, $tree[$ptr]['right'], $higher, $ptr, 'right' );
if( $higher )
{
switch( $tree[$ptr]['bal'] )
{
case -1:
$tree[$ptr]['bal'] = 0;
$higher = false;
break;
case 0:
$tree[$ptr]['bal'] = 1;
break;
case 1:
$ptr1 = $tree[$ptr]['right'];
if( $tree[$ptr1]['bal'] == 1 )// individualli flip RR
{

$tree[$ptr]['right'] = $tree[$ptr1]['left'];
$tree[$ptr1]['left'] = $ptr;

$tree[$ptr]['bal'] = 0;

if( $ptr == $beginning )
$beginning = $ptr1;
replace_pointer_link( $ptr, $ptr1 );
$ptr = $ptr1;
}
else//RL
{

$ptr2 = $tree[$ptr1]['left'];

$tree[$ptr1]['left'] = $tree[$ptr2]['right'];
$tree[$ptr2]['right'] = $ptr1;

$tree[$ptr]['right'] = $tree[$ptr2]['left'];
$tree[$ptr2]['left'] = $ptr;

if( $tree[$ptr2]['bal'] == 1 )
$tree[$ptr]['bal'] = -1;
else
$tree[$ptr]['bal'] = 0;

if( $tree[$ptr2]['bal'] == -1 )
$tree[$ptr1]['bal'] = 1;
else
$tree[$ptr1]['bal'] = 0;

if( $ptr == $beginning )
$beginning = $ptr2;

replace_pointer_link( $ptr, $ptr2 );
$ptr = $ptr2;
}
$tree[$ptr]['bal'] = 0;
$higher = false;
break;
}
}
}
else
{
$tree[$ptr]['count']++;
$higher = false;
}
}
return $beginning;
}
//replaces $old_ptr with $new_ptr in the parent node's left or right node
function replace_pointer_link( $old_ptr, $new_ptr )
{
global $tree;

for( $i=0; $i < count($tree); $i++)
{
if( $i === $new_ptr )
continue;//prevents replacing $old_ptr with $new_ptr in $tree[$new_ptr]

// if $tree[$i]['left'] is empty and we are checking for link to node 0($old_ptr=0),
// ('' == 0)==true, but ('' === 0)==false
// we don't need to put link to node 0 on empty nodes
if( $tree[$i]['left'] === $old_ptr ){
$tree[$i]['left'] = $new_ptr;
return;
}
elseif( $tree[$i]['right'] === $old_ptr)
{
$tree[$i]['right'] = $new_ptr;
return;
}
}

}
//
// Example:
//

$my_tree = array();
// you could create as many trees as you want
// but when you want to work with them use $tree = &$my_tree;
$tree = &$my_tree;
$start = 0;

// test all 4 cases of rebalancing when
// adding element in balanced tree
$values = array( 4, 5, 7, 2, 1, 3, 6);
foreach( $values as $val )
{
$start = search_btree( $val, $start, false);
}
echo "<html><body>";
echo "start=$start;";
echo "<pre>";
print_r( $my_tree );
echo "</pre>";
echo "<br><br>";
echo "</body></html>";

?>


Source

No comments: