java平衡二叉樹的增加刪除等基本操作和程式碼實現
阿新 • • 發佈:2018-12-15
陣列為{1,2,3}型別的 五種型別四種調整
一、LL型:
/** * 帶左子樹旋轉,適用於LL型 */ public static AvlNode rotateWithLeftChild(AvlNode n) { AvlNode k = n.left; n.left = k.right; k.right = n; n.height = Math.max(height(n.left), height(n.right)) + 1; k.height = Math.max(height(k.left), n.height) + 1; return k; }
二、RR型:
/** * 帶右子樹旋轉,適用於RR型 */ public static AvlNode rotateWithRightChild(AvlNode n) { AvlNode k = n.right; n.right = k.left; k.left = n; n.height = Math.max(height(n.left), height(n.right)) + 1; k.height = Math.max(height(k.right), n.height) + 1; return k; }
三、LR型:
/**
* 雙旋轉,適用於LR型
*/
public static AvlNode doubleWithLeftChild(AvlNode n) {
n.left = rotateWithRightChild(n.left);
return rotateWithLeftChild(n);
}
四、RL型:
/** * 雙旋轉,適用於RL型 */ public static AvlNode doubleWithRightChild(AvlNode n) { n.right = rotateWithLeftChild(n.right); return rotateWithRightChild(n); }
四種類型最終都變為:
宣告樹的節點類:
package TN;
public class AvlNode {
public Integer num;
public int height;
public String name;
public AvlNode left,right,pre;
AvlNode(){
pre=left=right=null;
height = 0;
}
AvlNode(Integer num,String name){
this.num=num;
this.name=name;
pre=left=right=null;
height = 0;
}
@Override
public String toString() {
return "AvlNode [num=" + num + ", height=" + height + ", name=" + name + ", left=" + left + ", right=" + right
+ ", pre=" + pre + "]";
}
}
操作類:
package TN;
import TN.AvlNode;
public class AvlTree {
private static AvlNode root;// AVL樹根
/**
* 初始化樹
*/
public AvlTree() {
root =new AvlNode(1,"我是1");
}
//求樹的高度
public static int height(AvlNode n) {
return n == null ? -1 : n.height;
}
/**
* 帶左子樹旋轉,適用於LL型
*/
public static AvlNode rotateWithLeftChild(AvlNode n) {
AvlNode k = n.left;
n.left = k.right;
k.right = n;
n.height = Math.max(height(n.left), height(n.right)) + 1;
k.height = Math.max(height(k.left), n.height) + 1;
return k;
}
/**
* 帶右子樹旋轉,適用於RR型
*/
public static AvlNode rotateWithRightChild(AvlNode n) {
AvlNode k = n.right;
n.right = k.left;
k.left = n;
n.height = Math.max(height(n.left), height(n.right)) + 1;
k.height = Math.max(height(k.right), n.height) + 1;
return k;
}
/**
* 雙旋轉,適用於LR型
*/
public static AvlNode doubleWithLeftChild(AvlNode n) {
n.left = rotateWithRightChild(n.left);
return rotateWithLeftChild(n);
}
/**
* 雙旋轉,適用於RL型
*/
public static AvlNode doubleWithRightChild(AvlNode n) {
n.right = rotateWithLeftChild(n.right);
return rotateWithRightChild(n);
}
/**
* 判斷是否為空
*/
public static boolean isEmpty() {
return root == null;
}
/**
* 排序輸出AVL樹, 採用中序輸出
*/
public static void printTree() {
if (isEmpty())
System.out.println("Empty tree");
else
printTree(root);
}
/**
* 中序遍歷AVL樹
*/
private static void printTree(AvlNode n) {
if (n != null) {
printTree(n.left);
System.out.print(n.num + " ");
printTree(n.right);
}
}
/**
* 在AVL樹中插入資料
*/
public static void insert(Integer x,String name) {
root = insert(x, name,root);
}
public static AvlNode insert(Integer num,String name,AvlNode root) {
if (root == null) {
return new AvlNode(num,name);
}
int compareResult = num.compareTo(root.num);
if (compareResult < 0) {
root.left = insert(num,name, root.left);// 將x插入左子樹中
if (height(root.left) - height(root.right) == 2)// 打破平衡
if (num.compareTo(root.left.num) < 0)// LL型(左左型)
root = rotateWithLeftChild(root);
else
root = doubleWithLeftChild(root); // LR型(左右型)
} else if (compareResult > 0) {
root.right = insert(num,name, root.right);// 將x插入右子樹中
if (height(root.right) - height(root.left) == 2)// 打破平衡
if (num.compareTo(root.right.num) > 0)
root = rotateWithRightChild(root);// RR型(右右型)
else
root = doubleWithRightChild(root);// RL型
} else
; // 重複資料,什麼也不做
root.height = Math.max(height(root.left), height(root.right)) + 1;// 更新高度
return root;
}
public static AvlNode find(AvlNode root,Integer num) {
AvlNode point=new AvlNode();
//AvlNode copy=new AvlNode();
point=root;
while(point != null) {
if(num==point.num) {
return point;
}
else if(num>point.num) {
if(point.right==null) {
System.out.println("該學生不存在");
return null;
}
else
point=point.right;
}
else {
if(point.left==null) {
System.out.println("該學生不存在");
return null;
}
else
point=point.left;
}
}
return null;
}
/**
* 在AVL樹中刪除
*/
public static void delete(Integer x) {
root = delete(root,x);
}
public static AvlNode delete(AvlNode root,Integer num) {//height
AvlNode point=null;
if(root == null){ // 沒有找到刪除的節點
return null;
}
if(num < root.num){ // 在左子樹上刪除
root.left = delete(root.left, num);
if(height(root.right) - height(root.left) > 1){ // 在左子樹上刪除,右子樹高度一定不小於左子樹高度
if(height(root.right.left) > height(root.right.right)){
root = doubleWithRightChild(root);//RL
}else{
root = rotateWithRightChild(root);//RR
}
}
}
else if(num == root.num){ // 找到刪除的節點
if(root.left != null && root.right != null){ // 刪除的節點既有左子樹又有右子樹
point=root.right;
while(point.left!=null)
point=point.left;
root.num = point.num; // 將失衡點的num域更改為其直接後繼節點的num域
root.name = point.name;
root.right = delete(root.right, root.num); // 將問題轉換為刪除其直接後繼節點
}else{ // 只有左子樹或者只有右子樹或者為葉子結點的情況
root = (root.left == null) ? root.right : root.left;
}
}
else{ // 在root的右子樹上查詢刪除節點
root.right = delete(root.right, num);
if(height(root.left) - height(root.right) > 1){
if(height(root.left.left) > height(root.left.right)){
root =rotateWithLeftChild(root);//LL
}else{
root = doubleWithLeftChild(root);//LR
}
}
}
if(root != null){ // 更新root的高度值
root.height = Math.max(height(root.left), height(root.right)) + 1;
}
return root;
}
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
//增加
Integer[] arr = {1,2,3,4,5,6,7,8,9,10,11,12,13};
for(int i=0;i<arr.length;i++) {
AvlTree.insert(arr[i],"我是"+arr[i]);
}
//中序遍歷
AvlTree.printTree();
System.out.println();
//查詢
AvlNode find=find(root,12);
System.out.println(find.name);
//刪除
AvlTree.delete(12);
AvlTree.printTree();
}
}