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
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞