概述
二叉排序樹又稱“二叉查找樹”、“二叉搜索樹”。二叉排序樹:或者是一棵空樹,或者是具有下列性質的二叉樹:
- 若它的左子樹不空,則左子樹上所有結點的值均小於它的根結點的值;
- 若它的右子樹不空,則右子樹上所有結點的值均大於它的根結點的值;
- 它的左、右子樹也分別爲二叉排序樹。
理論參考
http://www.cnblogs.com/zhuyf87/archive/2012/11/09/2763113.html
http://blog.chinaunix.net/uid-22663647-id-1771796.html
http://blog.csdn.net/hackbuteer1/article/details/6583988
代碼(PHP)
1.二叉樹類
在這個類中完成基本二叉樹定義,包括定義屬性(當前節點值,左子樹,右子樹)和一些基本方法(先序遍歷,中序遍歷,後序遍歷)。
//定義一個二叉樹
class BTree{
protected $key = null;//當前節點值
protected $left = null;//左子樹
protected $right = null;//右子樹
//構造函數
public function __construct($i_key=null,$i_left=null,$i_right=null){
$this->key = $i_key;
$this->left = $i_left;
$this->right = $i_right;
}
//析構函數
public function __destruct(){
$this->key = null;
$this->left = null;
$this->right = null;
}
//先序遍歷,非遞歸實現
public function preOrderTraversal(){
$arr = array();
$stack=array();
$temp_tree = $this;
while($temp_tree != null){
$arr[] = $temp_tree->key;
array_push($stack,$temp_tree);
$temp_tree = $temp_tree->left;
}
while(!empty($stack)){
$temp_tree = array_pop($stack);
$temp_tree = $temp_tree->right;
while($temp_tree != null){
$arr[] = $temp_tree->key;
array_push($stack,$temp_tree);
$temp_tree = $temp_tree->left;
}
}
return $arr;
}
//中序遍歷,非遞歸實現
public function inOrderTraversal(){
$arr= array(); //存放遍歷結果
$stack = array();//存放節點棧
$temp_tree =$this;
while($temp_tree != null || !empty($stack)){
while($temp_tree != null){
array_push($stack,$temp_tree);
$temp_tree = $temp_tree->left;
}
if(!empty($stack)){
$temp_tree = array_pop($stack);
$arr[]=$temp_tree->key;
$temp_tree = $temp_tree->right;
}
}
return $arr;
}
//後續遍歷,非遞歸實現
public function postOrderTraversal(){
$arr= array(); //存放遍歷結果
$stack = array();//存放節點棧
$temp_tree =$this;
$previsit =null;
while($temp_tree != null || !empty($stack)){
while($temp_tree !=null){
array_push($stack,$temp_tree);
$temp_tree =$temp_tree->left;
}
$temp_tree = array_pop($stack);
if($temp_tree->right == null || $temp_tree->right == $previsit){
$arr[] = $temp_tree->key;
$previsit = $temp_tree;
$temp_tree = null;
}else{
array_push($stack,$temp_tree);
$temp_tree = $temp_tree->right;
}
}
return $arr;
}
}
2.二叉排序樹類
該類繼承與二叉樹類(BTree),完成二叉排序樹的插入節點,查找節點,刪除節點。
//定義二叉排序樹
class BinarySortTree extends BTree{
//插入一個節點到當前樹中
public function insertNode($key){
if($this->key == null){//如果是空樹,插入到首節點。
$this->key = $key;
return;
}
$temp_tree =$this;//當前子樹
while($temp_tree !=null){
if($temp_tree->key == $key){
break;
}
if($temp_tree->key > $key){//左子樹
if($temp_tree->left == null){
$temp_tree->left = new BinarySortTree($key);
break;
}else{
$temp_tree = $temp_tree->left;
}
}
if($temp_tree->key < $key){//右子樹插入
if($temp_tree->right == null){
$temp_tree->right = new BinarySortTree($key);
break;
}else{
$temp_tree = $temp_tree->right;
}
}
}
}
//查找一個節點,找到返回該節點及其子樹,否則返回null
public function searchNode($key){
$temp_tree =$this;//當前子樹
while($temp_tree !=null){
if($temp_tree->key == $key){
break;
}
if($temp_tree->key > $key){//左子樹
if($temp_tree->left == null){
$temp_tree = null;
break;
}else{
$temp_tree = $temp_tree->left;
}
}
if($temp_tree->key < $key){//右子樹插入
if($temp_tree->right == null){
$temp_tree=null;
break;
}else{
$temp_tree = $temp_tree->right;
}
}
}
return $temp_tree;
}
//刪除一個節點
public function deleteNode($key){
$parent_tree =null;//要刪除節點的父節點樹
$temp_tree = $this;//要刪除的節點
$in_side = 0; //要刪除的節點在父節點樹的哪邊
//找到要刪除的節點極其父節點
while($temp_tree !=null && ($temp_tree->key != $key)){
if($temp_tree->key > $key){//左子樹
if($temp_tree->left == null){
$temp_tree = null;
break;
}else{
$in_side =0;
$parent_tree = $temp_tree;
$temp_tree = $temp_tree->left;
}
}else{//右子樹
if($temp_tree->right == null){
$temp_tree=null;
break;
}else{
$in_side =1;
$parent_tree = $temp_tree;
$temp_tree = $temp_tree->right;
}
}
}
//根據不同情況進行刪除操作
if($temp_tree != null){//當前節點存在
$p_side =null;
//開始刪除
if($temp_tree->left == null){
//如果要刪除節點左邊爲空,就將右邊賦給parent;
$p_side = $temp_tree->right;
}else if($temp_tree->right == null){
//如果要刪除節點右邊邊爲空,就將左邊賦給parent;
$p_side = $temp_tree->left;
}else{
//都不爲空,找到要刪除節點左子樹的最大的節點,極其該節點的父節點
$lMax =$temp_tree->right;//左子樹最大節點
$p_lMax = $temp_tree;
while($lMax->right != null){
if($lMax->right->right == null){
$p_lMax = $lMax;
}
$lMax = $lMax->right;
}
$p_lMax->right = $lMax->left;
$lMax->left = $temp_tree->left;
$lMax->right = $temp_tree->right;
$p_side = $lMax;
}
//設置父節點
if($parent_tree != null){//不是根節點刪除
//引用當前父節點的某一邊。
if($in_side == 0){
$parent_tree->left = $p_side;
}else{
$parent_tree->right = $p_side;
}
}else{
$this->key = $p_side->key;
$this->left = $p_side->left;
$this->right = $p_side->right;
}
}
}
}
3.調用
$item = array(50, 30, 20,35,33,40,36, 100, 56, 78);
$root = new BinarySortTree();
foreach($item as $key){
$root->insertNode($key);
}
var_dump($root);
echo '先序遍歷:'.implode(',',$root->preOrderTraversal()).'<br>';
echo '中序遍歷:'.implode(',',$root->inOrderTraversal()).'<br>';
echo '後序遍歷:'.implode(',',$root->postOrderTraversal()).'<br>';
$root->deleteNode('30');
echo '刪除節點後的先序遍歷:'.implode(',',$root->preOrderTraversal()).'<br>';