PHP 实现见得的二叉排序树查找算法

<?php
//树表查找,二叉排序树
//基本特点:
//1.左子树要么是空要么key值小于父亲结点key 2.右子树要么是空要么大于父亲结点key
//左右孩子又是一棵二叉排序树

//时间复杂度
//查找的次数(关键之比较次数)不会超过树的深度,对于不同形态的树的形状平均查找的次数不同,
//最坏的情况退化的单链表,为O(n)

//平均查找长度为log2(n)
//比二分查找更容易维护

define('LEN',10);
class node //结点
{
    public $key;
    public $data;
    public $left;
    public $right;
}
/**
 * 插入结点
 * @param null|node $node
 * @param int $key
 * @return number
 */
function insertBST(&$node,$key)//这里可能要修改node 要用引用,应为node可能为null
{
    if(!$node instanceof node){ //如果是一个空结点
        $node = new node();
        $node->data = 'val:'.$key;
        $node->key  = $key;
        $node->left = $node->right = null;
        return 1;
    }else if($node->key == $key){
        return 0;
    }else if($key<$node->key){ //如果key值小于父亲结点那么左子树递归插入
        return insertBST($node->left, $key);
    }else {
        return insertBST($node->right, $key); //右子树递归插入
    }
}
$arr = range(1, LEN);
shuffle($arr);
/**
 * 生成二叉排序树
 * @param array $arr
 * @return node
 */
function createBST($arr)
{
    $bt = null;
    foreach ($arr as $val){
        insertBST($bt, $val);		
    }
    
    return $bt;
}

$bt  = createBST($arr);

//中序遍历树将得到一个升序,检查二叉排序树是否创建正确
function orderRes($root)
{
    if($root!=NUll){
        orderRes($root->left);
        echo $root->key,',';
        orderRes($root->right);
    }
}

//经过测试正确
//orderRes($bt);
function searchBST($node,$key)
{
    if($node==NULL||$node->key==$key){
        return $node;
    }
    if($key>$node->key){
        return searchBST($node->right, $key);
    }else{
        return searchBST($node->left, $key);
    }	
}

$res = searchBST($bt, 10);
if($res!=NULL){
    echo $res->key,'=>',$res->data,'<br/>';
}

/**
 * 删除一个结点
 * 三种情况:
 * 1.要删除的结点是叶子结点,直接删除
 * 2.要删除的叶子结点有且只有一颗子树,把子树替换到该结点,并且删除该结点
 * 3.删除的结点有左右子树,两种删除方法
 * 		(1).在左子树中找到最大的一个结点node(node结点必定在左子树的最右边,即node没有右子树),
 * 			先将node保存出来node1,然后将node的左子树替换成node,即node = node->left,
 * 			并且将node1替换成要删除的结点,删除要删除的结点
 * 		(2).在右子树中找到最小的一个结点node(node结点必定在右子树的最左边,即node没有左子树),
 * 			先将node保存出来node1,然后将node天的右子树替换成node,即node = node->right,
 * 			并且将node1替换成要删除的结点,删除要删除的结点
 */
function deleteBST(&$bt,$key)
{
    if($bt==NULL){
        return 0;
    }else {
        if($bt->key>$key){
            return deleteBST($bt->left, $key);
        }else if($bt->key<$key){
            return deleteBST($bt->right, $key);
        }else{
            //找到对应的key结点删除
            deleteNode($bt);
        }
    }
}

function deleteNode(&$bt)
{
    if($bt->left==NULL&&$bt->right==NULL){ //叶子节点
        $bt = NULL;
        unset($bt);
    }else if(!($bt->left!=NULL&&$bt->right!=NULL)){ //只有一颗子树
        $bt  = $bt->left==NULL?$bt->right:$bt->left;
    }else{
        //有左右子树
        deleteNodeLeft($bt,$bt->left); //在左子树中找到一个最大的点代替bt
    }
}

/**
 * 用左子树最大节点代替被删除的子树 $bt
 * @param string $bt
 */
function deleteNodeLeft(&$bt,&$r)
{
    if($r->right==NULL){//找到最大的结点
        $bt = $r; //替换要删除的结点
        $r  = $r->left;	//将r的左子树替换成r
    }else{
        deleteNodeLeft($bt, $r->right);
    }
}

deleteBST($bt, 1);
orderRes($bt);
$res = searchBST($bt, 1);

//var_dump($res);
echo '<br/>',memory_get_usage()/1024;

?>

    原文作者:二叉查找树
    原文地址: https://blog.csdn.net/u010541899/article/details/24351429
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞