1. 程式人生 > >平衡二叉樹建立及其增刪改查(JAVA)

平衡二叉樹建立及其增刪改查(JAVA)

平衡二叉樹:指的是左右子樹高度差的絕對值不超過一的二叉排序樹

主要思路:1、用左高度跟右高度代替平衡因子,大於1進行L~調整,小於-1進行R~調整

                  2、每次插入都通過遞迴計算一次各結點高度,然後進行旋轉調整

                  3、判斷旋轉操作時只需判斷從失衡節點開始前兩個節點  LL:左左左  、 RR:右右右  、 LR:左右~  、RL:右左~

想要實現平衡二叉樹的建立,就要了解它的四種旋轉調節方式:LL 、RR 、LR 、RL

LL:這種調整是因為在失衡節點左孩子的左子樹插入結點造成的。

RR:這種調整是因為在失衡節點

右孩子的右子樹插入結點造成的。

LR:這種調整是因為在失衡節點左孩子的右子樹插入結點造成的。(圖稍後來補)

RL:這種調整是因為在失衡節點右孩子的左子樹插入結點造成的。

程式碼:

package test;

/** 
* @author HRX
* @version 建立時間:2018年10月3日 下午3:23:57 
* 類說明 
* 坑:1、t後還附帶孩6子節點,並不是單個節點(執行旋轉操作時)
*    2、BalanceTree tree = t;  tree跟t指向同一個記憶體地址
*    3、BalanceTree tree = new BalanceTree();  tree跟t不是同一個地址
*    4、判斷旋轉操作時只需判斷從失衡節點開始前兩個節點  LL:左左左  、 RR:右右右  、 LR:左右~  、RL:右左~
*    5、遞迴一定要加上=號,否則可能造成值傳不回來
*/
public class BalanceTree {
	private int data = 0;
	private BalanceTree nextLeftTree;	//左子樹
	private BalanceTree nextRightTree;	//右子樹
	private int Lheight = 0;		//左高度
	private int Rheight = 0;		//右高度
	BalanceTree(){}					//無參建構函式
	BalanceTree(int xdata){
		this.data = xdata;
	}
	
	//左旋調整
	public BalanceTree LL(BalanceTree t){		
		BalanceTree t1 = new BalanceTree();
		t1 = t.nextLeftTree;			//t1指向t的左孩子
		t.nextLeftTree = t1.nextRightTree;
		t1.nextRightTree = t;						//t1的右孩子指向t
		return t1; 
	}
	//右旋調整
	public BalanceTree RR(BalanceTree t){
		BalanceTree t1 = new BalanceTree();
		t1 = t.nextRightTree;			//t1指向t的右孩子
		t.nextRightTree = t1.nextLeftTree;
		t1.nextLeftTree = t;						//t1的左孩子指向t
		return t1; 
	}
	public BalanceTree LR(BalanceTree t){
		t.nextLeftTree = RR(t.nextLeftTree);
		t = LL(t);
		return t;
	}
	public BalanceTree RL(BalanceTree t){
		t.nextRightTree = LL(t.nextRightTree);
		t = RR(t);
		return t;
	}
	
	//保持平衡操作
	public BalanceTree ChangeToBalance(BalanceTree tree,int value){
		if(tree == null)
			return tree;
		AddHeight(tree);
		if(tree.Lheight - tree.Rheight > 1){
			if(value < tree.data && value >tree.nextLeftTree.data){
				System.out.println("執行LR平衡調整!");
				tree = LR(tree);
			}
			else{
				System.out.println("執行LL平衡調整!");
				tree = LL(tree);
			}
		}
		else if(tree.Lheight - tree.Rheight < -1){
			if(value > tree.data && value <tree.nextRightTree.data){
				System.out.println("執行RL平衡調整!");
				tree = RL(tree);
			}
			else{
					System.out.println("執行RR平衡調整!");
					tree = RR(tree);
			}
		}
		tree.nextLeftTree = ChangeToBalance(tree.nextLeftTree,value);			//注意一定要等於  值傳遞!!!!!!!
		tree.nextRightTree = ChangeToBalance(tree.nextRightTree,value);
		return tree;
	}
	//計算各節點左右子樹高度
	public void AddHeight(BalanceTree tree){
		if(tree == null)
			return;
		AddHeight(tree.nextLeftTree);				//上下順序很重要
		AddHeight(tree.nextRightTree);
		tree.Lheight = maxHeight(tree.nextLeftTree);
		tree.Rheight = maxHeight(tree.nextRightTree);
	}
	//輔助計算左右子樹高度
	public int maxHeight(BalanceTree tree){
		if(tree != null)
			return tree.Lheight >= tree.Rheight ? tree.Lheight+1 : tree.Rheight+1;
		else
			return 0;
	}
	
	//遍歷二叉樹(中序遍歷)
	public static void ergodic (BalanceTree tree){
		if(tree == null) return;
		System.out.println(tree.data);
		ergodic(tree.nextLeftTree);
		ergodic(tree.nextRightTree);
	}
	
	//插入操作
	public BalanceTree InTree(BalanceTree tree , int value){
		BalanceTree tree2 = new BalanceTree();
		if(tree.data == 0){
			tree.data = value;
			return tree;
		}
		tree2 = tree;
		while(tree2 != null){
			if(value < tree2.data){
				System.out.println("左"+"value:"+value);
				if(tree2.nextLeftTree != null){
					tree2 = tree2.nextLeftTree;
				}
				else{
					tree2.nextLeftTree = new BalanceTree(value);
					break;
				}
			}
			if(value >= tree2.data){
				System.out.println("右"+"value:"+value);
				if(tree2.nextRightTree != null){
					tree2 = tree2.nextRightTree;
				}
				else{
					tree2.nextRightTree = new BalanceTree(value);
					break;
				}
			}
		}
		System.out.println((tree.Lheight +":::" +tree.Rheight));
		tree = ChangeToBalance(tree,value);
		return tree;
	} 
	
	//查詢節點
	public BalanceTree findNode (BalanceTree tree ,int value){
		while(tree !=null){
			if(value < tree.data)
				tree = tree.nextLeftTree;
			else if(value > tree.data)
				tree = tree.nextRightTree;
			else if(value == tree.data)
				return tree;
		}
		System.out.println("不存在要查詢的資料!!!!");
		return null;
	}
	
	//刪除節點
	public BalanceTree deleteNode (BalanceTree tree ,int value){
		BalanceTree t = new BalanceTree();
		BalanceTree parent = null;			//一定要是null作為是否是刪除根節點的判斷
		t = tree;
		while(tree !=null&&value != t.data){
			parent = t;
			if(value < t.data)
				t = t.nextLeftTree;
			else if(value > t.data)
				t = t.nextRightTree;
		}
		if(t == null)
			System.out.println("不存在要刪除的資料!!!!");
		else if(t.nextLeftTree !=null && t.nextRightTree != null){
			BalanceTree tree2 = t.nextRightTree;
			BalanceTree pre = t;
			while(tree2.nextLeftTree != null){
				pre = tree2;
				tree2 = tree2.nextLeftTree;
			}
			t.data = tree2.data;
			if(pre == t)
				pre.nextRightTree = tree2.nextRightTree;		//不需要判斷tree2.nextRightTree 是不是null,為空就給他賦值為空
			else
				pre.nextLeftTree = tree2.nextRightTree;
		}
		else{
			BalanceTree tree3;
			if(t.nextLeftTree == null) tree3 = t.nextRightTree;
			else tree3 = t.nextLeftTree;
			if(parent == null)
				return tree3;
			else if(parent.nextLeftTree == t) parent.nextLeftTree = tree3;
			else parent.nextRightTree = tree3;
		}
		return tree;
	}
	
	//修改節點
	public BalanceTree changeNode (BalanceTree tree ,int oldvalue ,int newvalue){
		BalanceTree t = new BalanceTree();							//會破壞排序樹的性質
		t = tree;
		while(tree !=null){
			if(oldvalue < t.data)
				t = t.nextLeftTree;
			else if(oldvalue > t.data)
				t = t.nextRightTree;
			else if(oldvalue == t.data){
				t.data = newvalue;
				return tree;
			}
		}
		System.out.println("不存在要修改的資料!!!!");
		return tree;
	}
	public static void main(String[] args) {
		BalanceTree aBalanceTree = new BalanceTree();
//		int[] num = {20,12,6,28,16,36,32,10,2,30,8};
		int[] num = {20,12,6,28,16,36,32};
		for(int n : num){
			aBalanceTree = aBalanceTree.InTree(aBalanceTree, n);
		}
		ergodic(aBalanceTree);
		System.out.println("-------------------------------");
		BalanceTree aaa = aBalanceTree.deleteNode(aBalanceTree, 32);
		ergodic(aaa);
	}
}