1. 程式人生 > >java平衡二叉樹的增加刪除等基本操作和程式碼實現

java平衡二叉樹的增加刪除等基本操作和程式碼實現

陣列為{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();
 
		
		
	}
 
}