<?php
$list = [];
function main() {
$arr = [1, 2, 6, 6, 7, 5, 4, 3, 8, 10, 9];
$count = count($arr);
$needReverse = true; //是否需要再繼續向上找 對樹進行平衡操作
$root = ''; //根節點
for($i=0;$i<$count;$i++) {
insert($root, $arr[$i], $needReverse);
}
}
function insert(&$root, $value, &$needReverse) {
global $list;
echo "需要插入的值是{$value}\n";
if(empty($root)) {//插入節點 樹有變化需要繼續向上找 看是否需要對樹進行平衡操作
$list[$value] = [
'Lvalue' => '', //左孩子值
'Rvalue' => '', //右孩子值
'balanceValue' => 0, //平衡因子
];
$root = $value; //根節點
$needReverse = true;
} else {
if($root == $value) { //如果插入的值重複 那麼不插入
$needReverse = false;
return false;
} elseif($value < $root) { //如果插入的值小於父節點
if(!insert($list[$root]['Lvalue'], $value, $needReverse)) {//向父節點的左側插入 如果插入失敗 返回false 說明有重複的值
return false;
}
if($needReverse) {//如果插入節點成功 需要對樹進行平衡判斷 修改最小不平衡樹
switch($list[$root]['balanceValue']) {
case 0: //父節點本來的平衡因子如果是0 因爲是像左插入 所以平衡因子變成1 樹的高度改變 需要繼續進行平衡操作
$list[$root]['balanceValue'] = 1; $needReverse=true; break;
break;
case 1://父節點本來的平衡因子如果是1 說左子樹比右子樹高一 左插入後 平衡因子變爲2 此時需要進行轉換
leftBalance($root); $needReverse=false; break;
break;
case -1://父節點本來的平衡因子是-1 說明右子樹比左子樹高一 左插入後 平衡因子變爲0 樹的高度沒有改變 不需要進行平衡操作
$list[$root]['balanceValue'] = 0; $needReverse=false; break;
break;
}
}
} else {//如果插入的值大於父節點
if(!insert($list[$root]['Rvalue'], $value, $needReverse)) {//向父節點的右側插入 如果插入失敗 返回false 說明有重複的值
return false;
}
if($needReverse) {//如果插入節點成功 需要對樹進行平衡判斷 修改最小不平衡樹
switch($list[$root]['balanceValue']) {
case 0: //父節點本來的平衡因子如果是0 因爲是像右插入 所以平衡因子變成-1 樹的高度改變 需要繼續進行平衡操作
$list[$root]['balanceValue'] = -1; $needReverse=true; break;
break;
case 1://父節點本來的平衡因子如果是1 說左子樹比右子樹高一 右插入後 平衡因子變爲0 樹的高度未改變 不需要繼續進行平衡操作
$list[$root]['balanceValue'] = 0; $needReverse=false; break;
break;
case -1://父節點本來的平衡因子是-1 說明右子樹比左子樹高一 右插入後 平衡因子會變成-2 此時需要進行轉換
rightBalance($root, $list); $needReverse=false; break;
break;
}
}
}
}
return true;
}
//右樹高的時候對最小不平衡樹的處理方式
function rightBalance(&$root) {
global $list;
$value = $root;
$Rvalue = $list[$root]['Rvalue'];
switch($list[$Rvalue]['balanceValue']) {
case -1://如果中間節點 的平衡因子是-1 說明他的結構是 右右的結構 即\的結構 這時候做左旋
LBalance($root);
//左旋後 父節點的平衡因子本來是-1 說明右比左高一 旋轉過程中父節點的右指針會指向右節點的左子節點 所以父節點的右子樹少一層 平衡因子 +1 變爲0
$list[$root]['balanceValue'] = 0;
//左旋後 右節點的平衡因子本來是-1 說明右比左高一 旋轉過程中父節點會作爲右節點的左子節點 導致右節點的左子節點高一層 平衡因子變爲 +1 變爲0
$list[$Rvalue]['balanceValue'] = 0;
break;
case 1:// 如果中間節點的平衡因子是1 說明他的結構是 右左的結構 即>的結構 這時候先右旋 然後再左旋
$RLValue = $list[$Rvalue]['Lvalue'];
switch($list[$RLValue]) {
case 0://如果右子樹的左子樹的平衡因子爲0
//右節點的平衡因子本來是1 右旋之後 右節點的左子節點的左右子樹高度相同 右節點的左指針指向左節點的右子樹 則右節點的左子樹高度減1即 1-1 = 0 隨後變成左子節點的右孩子 成爲第三層節點
$list[$Rvalue]['balanceValue'] = 1-1 = 0;
//右子樹的左子節點平衡因子本來是0 右旋之後 左子節點的右指針指向右子樹右側高度加一
$list[$RLValue]['balanceValue'] = 0-1 = -1;
//根節點的平衡因子本來是-1 可以當-2來算 左旋之後 根節點右指針指向轉換後的右節點的左子樹 即 -2+1+1 = 0
$list[$root]['balanceValue'] = -2+1+1 = 0 ;
//右左子樹的平衡因子本來是-1 左旋之後 左指針指向根節點 左子樹高度加1
$list[$RLValue]['balanceValue'] = -1+1 = 0;
break;
case -1: //如果右子樹的左子樹平衡因子爲-1
//右節點的平衡因子本來是1 右旋之後 右節點的左子節點的左比右矮1 右節點的左指針指向左節點的右子樹 則右節點的左子樹高度減1即 1-1 = 0 隨後變成左子節點的右孩子 成爲第三層節點
$list[$Rvalue]['balanceValue'] = 1-1 = 0;
//右子樹的左子節點平衡因子本來是-1 右旋之後 左子節點的右指針指向右子樹右側高度加一
$list[$RLValue]['balanceValue'] = -1-1 = -2;
//根節點的平衡因子本來是-1 可以當-2來算 左旋之後 根節點右指針指向轉換後的右節點的左子樹 所以根右子樹的高度-1 z再減2
$list[$root]['balanceValue'] = -2+2+1 = 1 ;
//右左子樹的平衡因子本來是-2 左旋之後 左指針指向根節點 -2 +2 = 0
$list[$RLValue]['balanceValue'] = -2+2 = 0;
break;
case 1: //如果右子樹的左子樹的平衡因子爲1
break;
}
RBalance($Rvalue);
LBalance($root);
break;
}
}
//左樹高的時候對最小不平衡樹的處理方式
function leftBalance(&$root) {
global $list;
$value = $root;
$Lvalue = $list[$root]['Lvalue'];
switch($list[$Lvalue]['balanceValue']) {
case 1://如果中間節點 的平衡因子是1 說明他的結構是 左左的結構 即/的結構 這時候做右旋
RBalance($root);
//右旋後 父節點的平衡因子本來是1 說明左比右高一 旋轉過程中父節點的左指針會指向左節點的右子節點 所以父節點的左子樹少一層 平衡因子 -1 變爲0
$list[$root]['balanceValue'] = 0;
//右旋後 左節點的平衡因子本來是1 說明左比右高一 旋轉過程中父節點會作爲左節點的右子節點 導致左節點的右子節點高一層 平衡因子變爲 -1 變爲0
$list[$Rvalue]['balanceValue'] = 0;
break;
case -1:// 如果中間節點的平衡因子是-1 說明他的結構是 左右的結構 即<的結構 這時候先左旋 然後再右旋
$LRValue = $list[$Lvalue]['Rvalue'];
switch($list[$LRValue]) {
case 0://如果左子樹的右子樹的平衡因子爲0
break;
case -1: //如果左子樹的右子樹平衡因子爲-1
break;
case 1: //如果左子樹的右子樹的平衡因子爲1
break;
}
LBalance($Lvalue);
RBalance($root);
break;
}
}
//純左旋
function LBalance(&$root) {
$Rvalue = $list[$root]['Rvalue'];
$list[$root]['Rvalue'] = $list[$Rvalue]['Lvalue'];
$list[$Rvalue]['Lvalue'] = $root;
$root = $Rvalue;
}
//純右旋
function RBalance(&$root) {
$Lvalue = $list[$root]['Lvalue'];
$list[$root]['Lvalue'] = $list[$Lvalue]['Rvalue'];
$list[$Lvalue]['Rvalue'] = $root;
$root = $Lvalue;
}
main();
我瘋了 沒寫完 大家幫忙補充吧 。。。 後續會繼續更新