平衡二叉树创建

<?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();

我疯了 没写完  大家帮忙补充吧 。。。 后续会继续更新

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章