<?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;
?>
PHP 实现见得的二叉排序树查找算法
原文作者:二叉查找树
原文地址: https://blog.csdn.net/u010541899/article/details/24351429
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
原文地址: https://blog.csdn.net/u010541899/article/details/24351429
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。