平衡二叉樹建立及其增刪改查(JAVA)
阿新 • • 發佈:2018-12-13
平衡二叉樹:指的是左右子樹高度差的絕對值不超過一的二叉排序樹。
主要思路: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); } }