數據結構第四章樹 平衡二叉樹,實現插入,刪除操作,Java實現,遞歸實現

二叉搜索樹自動調整平衡(左右子樹高度差小於等於1)——平衡二叉樹

目錄

1.編寫測試程序,測試二叉樹的四種平衡操作

2.編寫內部類:樹結點

3.根節點,類構造器

4.插入

5.平衡

5.1計算平衡值

5.2.計算深度 

5.3.平衡節點(調用四個旋轉的條件)

5.3.1. RR旋轉

5.3.2. LL旋轉

5.3.3. RL旋轉

5.3.4. LR旋轉

5.3.5. 逆時針旋轉

5.3.6 順時針旋轉

6.刪除 

6.1刪除無兒子節點

6.2 刪除有一個兒子的節點 

6.3 刪除有兩個兒子的節點 

 7.前序遍歷,用於驗證二叉樹

8.全部代碼如下



1.編寫測試程序,測試二叉樹的四種平衡操作

public class AVLTree {
	public static void main(String[] args) {
	//驗證插入操作
		BalancedBinaryTree test0 = new BalancedBinaryTree(100);	
		test0.insert(50);
		test0.insert(200);
		System.out.print("草稿紙上運算爲{100,50,200}: ");
		test0.preOrder();
		System.out.println();
		
	//驗證LL旋轉
		//發生在root
		BalancedBinaryTree test1 = new BalancedBinaryTree(100);	
		test1.insert(70);
		test1.insert(30);
		test1.insert(10);
		test1.insert(5);
		System.out.print("草稿紙上運算爲{70,10,5,30,100}: ");
		test1.preOrder();
		System.out.println();
		//發生在非root
		BalancedBinaryTree test4 = new BalancedBinaryTree(100);	
		test4.insert(50);
		test4.insert(200);
		test4.insert(150);
		test4.insert(130);
		System.out.print("草稿紙上運算爲{100,50,150,130,200 }: ");
		test4.preOrder();
		System.out.println();	
		
	//驗證RR旋轉
		//發生在root
		BalancedBinaryTree test2 = new BalancedBinaryTree(100);	
		test2.insert(200);
		test2.insert(300);
		test2.insert(400);
		test2.insert(500);
		System.out.print("草稿紙上運算爲{200,100,400,300,500}: ");
		test2.preOrder();
		System.out.println();
		//發生在非root
		BalancedBinaryTree test3 = new BalancedBinaryTree(100);	
		test3.insert(50);
		test3.insert(200);
		test3.insert(75);
		test3.insert(80);
		System.out.print("草稿紙上運算爲{100,75,50,80,200}: ");
		test3.preOrder();
		System.out.println();
		
	//驗證LR旋轉
		BalancedBinaryTree test5 = new BalancedBinaryTree(100);	
		test5.insert(50);
		test5.insert(200);
		test5.insert(75);
		test5.insert(30);
		test5.insert(80);
		System.out.print("LR草稿紙上運算爲{75,50,30,100,80,200}: ");
		test5.preOrder();
		System.out.println();
		
	//驗證RL旋轉
		BalancedBinaryTree test6 = new BalancedBinaryTree(100);	
		test6.insert(50);
		test6.insert(200);
		test6.insert(150);
		test6.insert(300);
		test6.insert(125);
		System.out.print("RL草稿紙上運算爲{150,100,50,125,200,300}: ");
		test6.preOrder();
		System.out.println();	
	
	
	//驗證刪除操作
		BalancedBinaryTree test7 = new BalancedBinaryTree(100);	
		test7.insert(50);
		test7.insert(200);
		test7.insert(150);
		test7.insert(300);
		test7.insert(25);
		test7.insert(75);
		System.out.print("delete草稿紙上運算爲{100,50,25,75,200,150,300}: ");
		test7.preOrder();
		System.out.println();
		
		//刪除沒有兒子的節點
		test7.delete(150);
		System.out.print("刪除沒有兒子的節點150,delete草稿紙上運算爲{100 50 25 75 200 300 }: ");
		test7.preOrder();
		System.out.println();
		//刪除有一個兒子的節點
		test7.delete(200);
		System.out.print("刪除有一個兒子的節點200,delete草稿紙上運算爲{100 50 25 75 200 300 }: ");
		test7.preOrder();
		System.out.println();
		//刪除有兩個兒子的節點
		test7.delete(100);
		System.out.print("刪除有兩個兒子的節點100,delete草稿紙上運算爲{75,50,25,300}: ");
		test7.preOrder();
		System.out.println();
		
		test7.delete(75);
		System.out.print("刪除節點75,delete草稿紙上運算爲{50,25,300}: ");
		test7.preOrder();
		System.out.println();
		
		test7.delete(50);
		System.out.print("刪除節點50,delete草稿紙上運算爲{25,300}: ");
		test7.preOrder();
		System.out.println();
	}
}

2.編寫內部類:樹結點

        class AVLNode {
		public int data;
		public int depth;//當前子樹深度的 depth
		public int balance;
		public AVLNode parent = null;//指向父節點的指針
		public AVLNode left = null;
		public AVLNode right = null;
		
		public AVLNode() {
			depth = 1;
			balance = 0;
			left = null;
			right = null;
		}
		
		public AVLNode(int data) {
			this.data = data;
			depth = 1;
			balance = 0;
			left = null;
			right = null;			
		}
	}

3.根節點,類構造器

class BalancedBinaryTree {
	/**
	 *  根節點
	 */
	private AVLNode root = null;
    /**
	 * 構造器
	 */
	public BalancedBinaryTree()	{		
	}
	
	public BalancedBinaryTree(int data)	{
		root = new AVLNode(data);
	}
    //以及別的操作
}

4.插入

插入過程分爲:二叉查找樹的插入過程+再平衡過程

再平衡過程分爲:計算深度和平衡值+進行平衡操作

        public void insert(int data) {
		if (root == null) {
			root = new AVLNode(data);
		} else {
			insertSon(root, data);
		}
	}
	
	private void insertSon(AVLNode node, int data) {
		if (data < node.data) {
			if (node.left != null) {
				insertSon(node.left, data);
			} else {
				node.left = new AVLNode(data);
				node.left.parent = node;//子節點鎖住parent
			}
		} else {
			if (node.right != null) {
				insertSon(node.right, data);
			} else {
				node.right = new AVLNode(data);
				node.right.parent = node;
			}
		}
		// 計算平衡和深度
		node.balance = calculateBalance(node);
		node.depth = calculateDepth(node);
		// 平衡節點
		balanceNode(node);
	}

5.平衡

5.1計算平衡值

        private int calculateBalance(AVLNode node) {
		int leftDepth;
		int rightDepth;
		if (node.left != null) {
			leftDepth = node.left.depth;
		} else {
			leftDepth = 0;
		}
		if (node.right != null) {
			rightDepth = node.right.depth;
		} else {
			rightDepth = 0;
		}
		return leftDepth - rightDepth;
	}

5.2.計算深度 

	private int calculateDepth(AVLNode node) {
		int depth = 0;
		if (node.left != null) {
			depth = node.left.depth;
		}
		if (node.right != null && depth < node.right.depth) {
			depth = node.right.depth;
		}
		depth++;
		return depth;
	}

5.3.平衡節點(調用四個旋轉的條件)

根據balance的數值,找出不平衡的地方進行調整操作(RR,RL,LR,LL)

        private void balanceNode(AVLNode node) {
		if (node.balance <= -2) {
			if (node.right.balance == -1) {
				// RR插入,RR旋轉
				rightRightRotate(node);
			} else {
				// RL插入,RL旋轉
				rightLeftRotate(node);
			}
		} else if (node.balance >= 2) {
			if (node.left.balance == 1) {
				// LL插入,LL旋轉
				leftLeftRotate(node);
			} else {
				// LR插入,LR旋轉
				leftRightRotate(node);
			}
		}
	}

5.3.1. RR旋轉

如圖A,B節點進行逆時針旋轉

圖片來源:中國MOOC浙大數據結構第四章

    public void rightRightRotate(AVLNode node) {
        counterClockwiseRotate(node);
    }

5.3.2. LL旋轉

如圖A,B兩個節點進行順時針旋轉

圖片來源:中國MOOC浙大數據結構第四章

 

        public void leftLeftRotate(AVLNode node) {
		clockwiseRotate(node);
	}

5.3.3. RL旋轉

先對C,B兩個節點先進行逆時針旋轉,再對A,C兩個節點順時針旋轉

圖片來源:中國MOOC浙大數據結構第四章

 

        public void rightLeftRotate(AVLNode node) {
		clockwiseRotate(node.right);
		counterClockwiseRotate(node);
	}

 

5.3.4. LR旋轉

先B,C逆時針旋轉,再A,B順時針旋轉

圖片來源:中國MOOC浙大數據結構第四章

        public void leftRightRotate(AVLNode node) {
		counterClockwiseRotate(node.left);
		clockwiseRotate(node);
	}

5.3.5. 逆時針旋轉

重新用回RR旋轉的圖,逆時針旋轉就是一個RR旋轉,本質就是交換A,B節點對別的節點的引用,再交換別的節點對A,B節點的引用而已。

        public void counterClockwiseRotate(AVLNode node) {
		AVLNode nodeOriginRight = node.right;
	//1.右子樹佔node位
		if(node.parent == null) { // 先確定是不是根節點,根節點不用處理parent
		
			nodeOriginRight.parent = null;
			root = nodeOriginRight;
		} else {
			if(node.parent.left.equals(node)) {
				node.parent.left = nodeOriginRight;
			} else {
				node.parent.right = nodeOriginRight;
			}
			nodeOriginRight.parent = node.parent;
		}
		 
	//2.node變成原右子樹的左子樹
		AVLNode bl = nodeOriginRight.left; 
		nodeOriginRight.left = node;
		node.parent = nodeOriginRight;
		
	//3.node新右子樹變爲原右子樹的的左子樹
		node.right = bl;
		if (bl != null) { // 有可能bl是null
			bl.parent = node;
		}
		node.balance = calculateBalance(node);
		node.depth = calculateDepth(node);
		nodeOriginRight.balance = calculateBalance(nodeOriginRight);
		nodeOriginRight.depth = calculateDepth(nodeOriginRight);
	}

5.3.6 順時針旋轉

就是逆時針操作反過來而已

        public void clockwiseRotate(AVLNode node) { 
		AVLNode nodeOriginLeft = node.left;
	// 1.左子樹佔node位
		if (node.parent == null) {
			nodeOriginLeft.parent = null;
			root = nodeOriginLeft;
		} else { // 更改node父節點的指向子結點指針
			if(node.parent.left.equals(node)) {
				node.parent.left = nodeOriginLeft;
			} else {
				node.parent.right = nodeOriginLeft;
			}
			nodeOriginLeft.parent = node.parent;
		} 
	//2.node變成原左子樹的右子樹
		AVLNode br = nodeOriginLeft.right; 
		nodeOriginLeft.right = node;
		node.parent = nodeOriginLeft;
		
	//3.node新左子樹變爲原左子樹的的右子樹
		node.left = br;
		if (br != null) {
			br.parent = node;
		}
		node.balance = calculateBalance(node);
		node.depth = calculateDepth(node);
		nodeOriginLeft.balance = calculateBalance(nodeOriginLeft);
		nodeOriginLeft.depth = calculateDepth(nodeOriginLeft);
	}

6.刪除 

刪除有三種情況,刪除節點沒有兒子,刪除節點有一個兒子,刪除節點有兩個兒子。

步驟爲:先比較大小確定是否是要刪除節點,再根據有幾個兒子調用不同的刪除方法,刪除完後進行平衡

        public void delete(int data) {
		if (root != null) {
			deleteDetail(root, data);
		}
	}
	
	private void deleteDetail(AVLNode node, int data) {
		if (data < node.data) {
			if (node.left != null) {
				deleteDetail(node.left, data);
			}
		} else if (data > node.data) {
			if(node.right != null) {
				deleteDetail(node.right, data);
			}
		} else { // 不大不小則是節點是要刪除節點
			if (node.left == null && node.right == null) { // 沒有兒子
				deleteSonWithNoChild(node);
			} else if (node.left == null || node.right == null) { // 有一個兒子
				deleteSonWithOneChild(node);			
			} else { // 有兩個兒子
				deleteSonWithTwoChild(node);
			}
		}
		// 計算平衡和深度
		// 由於node已被替換,且替換node的節點已經平衡過或不需要平衡,爲了整個遞歸的平衡過程,這裏平衡node的父節點
		if (node.parent != null) {
			node.parent.balance = calculateBalance(node.parent);
			node.parent.depth = calculateDepth(node.parent);
			// 平衡節點
			balanceNode(node.parent);
		}
	}

6.1刪除無兒子節點

父節點的引用改爲null即可

        private void deleteSonWithNoChild(AVLNode node) {
		if (node.parent == null) {
			root = null;
		} else if (node.parent.left == node) {
			node.parent.left = null;
		} else if (node.parent.right == node) {
			node.parent.right = null;
		}
	}

6.2 刪除有一個兒子的節點 

父節點的兒子引用指向孫子節點,孫子節點的父引用指向父節點

        private void deleteSonWithOneChild(AVLNode node) {
		AVLNode temporary = ((node.right == null) ? node.left : node.right);
		if (node.parent == null) {
			root = temporary;
		} else if (node.parent.left == node) {
			node.parent.left = temporary;
		} else if (node.parent.right == node) {
			node.parent.right = temporary;
		}
		temporary.parent = node.parent;
	}

6.3 刪除有兩個兒子的節點 

用左子樹的最大節點(也可以用右子樹最小節點)來替換被刪除節點,步驟爲:

1.保存左子最大樹節點數據

2.刪除左子最大樹節點(這個節點要麼沒兒子,要麼只有一個兒子)

3.將要被刪除節點數據替換爲左子最大樹節點數據(由於步驟2刪除過程已調過平衡,這個節點不用再調平衡)

        private void deleteSonWithTwoChild(AVLNode node) {
		AVLNode temporary = searchMax(node.left);// 左子樹最大的的節點可以替換刪除的node
		delete(temporary.data);
		node.data = temporary.data;// 直接換數據
	}

	private AVLNode searchMax(AVLNode node) {
		if (node.right == null) {
			return node;
		} else {
			return searchMax(node.right);
		}
	}

 7.前序遍歷,用於驗證二叉樹

        public void preOrder() {
		if (root != null) {
			 preOrderDetail(root);
		}
	}
	public void preOrderDetail(AVLNode node) {
		if (node != null) {
			System.out.print(node.data);
			System.out.print(" ");
			preOrderDetail(node.left);
			preOrderDetail(node.right);
		}
	}

8.全部代碼如下

package BinaryTree;
public class AVLTree {
	public static void main(String[] args) {
	// 驗證插入操作
		BalancedBinaryTree test0 = new BalancedBinaryTree(100);	
		test0.insert(50);
		test0.insert(200);
		System.out.print("草稿紙上運算爲{100,50,200}: ");
		test0.preOrder();
		System.out.println();
		
	// 驗證LL旋轉
		// 發生在root
		BalancedBinaryTree test1 = new BalancedBinaryTree(100);	
		test1.insert(70);
		test1.insert(30);
		test1.insert(10);
		test1.insert(5);
		System.out.print("草稿紙上運算爲{70,10,5,30,100}: ");
		test1.preOrder();
		System.out.println();
		// 發生在非root
		BalancedBinaryTree test4 = new BalancedBinaryTree(100);	
		test4.insert(50);
		test4.insert(200);
		test4.insert(150);
		test4.insert(130);
		System.out.print("草稿紙上運算爲{100,50,150,130,200 }: ");
		test4.preOrder();
		System.out.println();	
		
	// 驗證RR旋轉
		// 發生在root
		BalancedBinaryTree test2 = new BalancedBinaryTree(100);	
		test2.insert(200);
		test2.insert(300);
		test2.insert(400);
		test2.insert(500);
		System.out.print("草稿紙上運算爲{200,100,400,300,500}: ");
		test2.preOrder();
		System.out.println();
		// 發生在非root
		BalancedBinaryTree test3 = new BalancedBinaryTree(100);	
		test3.insert(50);
		test3.insert(200);
		test3.insert(75);
		test3.insert(80);
		System.out.print("草稿紙上運算爲{100,75,50,80,200}: ");
		test3.preOrder();
		System.out.println();
		
	// 驗證LR旋轉
		BalancedBinaryTree test5 = new BalancedBinaryTree(100);	
		test5.insert(50);
		test5.insert(200);
		test5.insert(75);
		test5.insert(30);
		test5.insert(80);
		System.out.print("LR草稿紙上運算爲{75,50,30,100,80,200}: ");
		test5.preOrder();
		System.out.println();
		
	// 驗證RL旋轉
		BalancedBinaryTree test6 = new BalancedBinaryTree(100);	
		test6.insert(50);
		test6.insert(200);
		test6.insert(150);
		test6.insert(300);
		test6.insert(125);
		System.out.print("RL草稿紙上運算爲{150,100,50,125,200,300}: ");
		test6.preOrder();
		System.out.println();	
	
	
	// 驗證刪除操作
		BalancedBinaryTree test7 = new BalancedBinaryTree(100);	
		test7.insert(50);
		test7.insert(200);
		test7.insert(150);
		test7.insert(300);
		test7.insert(25);
		test7.insert(75);
		System.out.print("delete草稿紙上運算爲{100,50,25,75,200,150,300}: ");
		test7.preOrder();
		System.out.println();
		
		// 刪除沒有兒子的節點
		test7.delete(150);
		System.out.print("刪除沒有兒子的節點150,delete草稿紙上運算爲{100 50 25 75 200 300 }: ");
		test7.preOrder();
		System.out.println();
		// 刪除有一個兒子的節點
		test7.delete(200);
		System.out.print("刪除有一個兒子的節點200,delete草稿紙上運算爲{100 50 25 75 200 300 }: ");
		test7.preOrder();
		System.out.println();
		// 刪除有兩個兒子的節點
		test7.delete(100);
		System.out.print("刪除有兩個兒子的節點100,delete草稿紙上運算爲{75,50,25,300}: ");
		test7.preOrder();
		System.out.println();
		
		test7.delete(75);
		System.out.print("刪除有兩個兒子的節點75,delete草稿紙上運算爲{50,25,300}: ");
		test7.preOrder();
		System.out.println();
		
		test7.delete(50);
		System.out.print("刪除有兩個兒子的節點50,delete草稿紙上運算爲{25,300}: ");
		test7.preOrder();
		System.out.println();
	}
}

class BalancedBinaryTree {// 本類對插入相同數值,刪除不存在數值的行爲不會有反應
	/**
	 *  節點
	 */
	class AVLNode {
		public int data;
		public int depth;
		public int balance;
		public AVLNode parent = null;
		public AVLNode left = null;
		public AVLNode right = null;
		
		public AVLNode() {
			depth = 1;
			balance = 0;
			left = null;
			right = null;
		}
		
		public AVLNode(int data) {
			this.data = data;
			depth = 1;
			balance = 0;
			left = null;
			right = null;			
		}
	}
	
	/**
	 * 根節點
	 */
	private AVLNode root = null;
	/**
	 * 構造器
	 */
	public BalancedBinaryTree() {
	}
	
	public BalancedBinaryTree(int data) {
		root = new AVLNode(data);
	}
	
	/**
	 *  插入
	 */
	public void insert(int data) {
		if (root == null) {
			root = new AVLNode(data);
		} else {
			insertSon(root, data);
		}
	}
	
	private void insertSon(AVLNode node, int data) {
		if (data < node.data) {
			if (node.left != null) {
				insertSon(node.left, data);
			} else {
				node.left = new AVLNode(data);
				node.left.parent = node;//子節點鎖住parent
			}
		} else {
			if (node.right != null) {
				insertSon(node.right, data);
			} else {
				node.right = new AVLNode(data);
				node.right.parent = node;
			}
		}
		// 計算平衡和深度
		node.balance = calculateBalance(node);
		node.depth = calculateDepth(node);
		// 平衡節點
		balanceNode(node);
	}
	
	/**
	 * 刪除
	 */
	public void delete(int data) {
		if (root != null) {
			deleteDetail(root, data);
		}
	}
	
	private void deleteDetail(AVLNode node, int data) {
		if (data < node.data) {
			if (node.left != null) {
				deleteDetail(node.left, data);
			}
		} else if (data > node.data) {
			if(node.right != null) {
				deleteDetail(node.right, data);
			}
		} else { // 不大不小則是節點是要刪除節點
			if (node.left == null && node.right == null) { // 沒有兒子
				deleteSonWithNoChild(node);
			} else if (node.left == null || node.right == null) { // 有一個兒子
				deleteSonWithOneChild(node);			
			} else { // 有兩個兒子
				deleteSonWithTwoChild(node);
			}
		}
		// 計算平衡和深度
		// 由於node已被替換,且替換node的節點已經平衡過或不需要平衡,爲了整個遞歸的平衡過程,這裏平衡node的父節點
		if (node.parent != null) {
			node.parent.balance = calculateBalance(node.parent);
			node.parent.depth = calculateDepth(node.parent);
			// 平衡節點
			balanceNode(node.parent);
		}
	}
	
	private void deleteSonWithNoChild(AVLNode node) {
		if (node.parent == null) {
			root = null;
		} else if (node.parent.left == node) {
			node.parent.left = null;
		} else if (node.parent.right == node) {
			node.parent.right = null;
		}
	}
	
	private void deleteSonWithOneChild(AVLNode node) {
		AVLNode temporary = ((node.right == null) ? node.left : node.right);
		if (node.parent == null) {
			root = temporary;
		} else if (node.parent.left == node) {
			node.parent.left = temporary;
		} else if (node.parent.right == node) {
			node.parent.right = temporary;
		}
		temporary.parent = node.parent;
	}
	
	private void deleteSonWithTwoChild(AVLNode node) {
		AVLNode temporary = searchMax(node.left);// 左子樹最大的的節點可以替換刪除的node
		delete(temporary.data);
		node.data = temporary.data;// 直接換數據
	}

	private AVLNode searchMax(AVLNode node) {
		if (node.right == null) {
			return node;
		} else {
			return searchMax(node.right);
		}
	}
	/**
	 * 計算平衡值
	 */
	private int calculateBalance(AVLNode node) {
		int leftDepth;
		int rightDepth;
		if (node.left != null) {
			leftDepth = node.left.depth;
		} else {
			leftDepth = 0;
		}
		if (node.right != null) {
			rightDepth = node.right.depth;
		} else {
			rightDepth = 0;
		}
		return leftDepth - rightDepth;
	}
	
	/**
	 * 計算深度
	 */
	private int calculateDepth(AVLNode node) {
		int depth = 0;
		if (node.left != null) {
			depth = node.left.depth;
		}
		if (node.right != null && depth < node.right.depth) {
			depth = node.right.depth;
		}
		depth++;
		return depth;
	}
	
	/**
	 * 平衡
	 */
	private void balanceNode(AVLNode node) {
		if (node.balance <= -2) {
			if (node.right.balance == -1) {
				// RR插入,RR旋轉
				rightRightRotate(node);
			} else {
				// RL插入,RL旋轉
				rightLeftRotate(node);
			}
		} else if (node.balance >= 2) {
			if (node.left.balance == 1) {
				// LL插入,LL旋轉
				leftLeftRotate(node);
			} else {
				// LR插入,LR旋轉
				leftRightRotate(node);
			}
		}
	}
	
	/**
	 * 旋轉
	 */
	// 四種旋轉
	public void rightRightRotate(AVLNode node) {
		counterClockwiseRotate(node);
	}
	
	public void rightLeftRotate(AVLNode node) {
		clockwiseRotate(node.right);
		counterClockwiseRotate(node);
	}
	
	public void leftRightRotate(AVLNode node) {
		counterClockwiseRotate(node.left);
		clockwiseRotate(node);
	}
	
	public void leftLeftRotate(AVLNode node) {
		clockwiseRotate(node);
	}
	
	// 兩個基本旋轉
	// 逆時針旋轉
	public void counterClockwiseRotate(AVLNode node) {
		AVLNode nodeOriginRight = node.right;
	//1.右子樹佔node位
		if(node.parent == null) { // 先確定是不是根節點,根節點不用處理parent
		
			nodeOriginRight.parent = null;
			root = nodeOriginRight;
		} else {
			if(node.parent.left.equals(node)) {
				node.parent.left = nodeOriginRight;
			} else {
				node.parent.right = nodeOriginRight;
			}
			nodeOriginRight.parent = node.parent;
		}
		 
	//2.node變成原右子樹的左子樹
		AVLNode bl = nodeOriginRight.left; 
		nodeOriginRight.left = node;
		node.parent = nodeOriginRight;
		
	//3.node新右子樹變爲原右子樹的的左子樹
		node.right = bl;
		if (bl != null) { // 有可能bl是null
			bl.parent = node;
		}
		node.balance = calculateBalance(node);
		node.depth = calculateDepth(node);
		nodeOriginRight.balance = calculateBalance(nodeOriginRight);
		nodeOriginRight.depth = calculateDepth(nodeOriginRight);
	}
	// 順時針旋轉:counterClockwiseRotate代碼反過來
	public void clockwiseRotate(AVLNode node) { 
		AVLNode nodeOriginLeft = node.left;
	// 1.左子樹佔node位
		if (node.parent == null) {
			nodeOriginLeft.parent = null;
			root = nodeOriginLeft;
		} else { // 更改node父節點的指向子結點指針
			if(node.parent.left.equals(node)) {
				node.parent.left = nodeOriginLeft;
			} else {
				node.parent.right = nodeOriginLeft;
			}
			nodeOriginLeft.parent = node.parent;
		} 
	//2.node變成原左子樹的右子樹
		AVLNode br = nodeOriginLeft.right; 
		nodeOriginLeft.right = node;
		node.parent = nodeOriginLeft;
		
	//3.node新左子樹變爲原左子樹的的右子樹
		node.left = br;
		if (br != null) {
			br.parent = node;
		}
		node.balance = calculateBalance(node);
		node.depth = calculateDepth(node);
		nodeOriginLeft.balance = calculateBalance(nodeOriginLeft);
		nodeOriginLeft.depth = calculateDepth(nodeOriginLeft);
	}
	
	/**
	 * 前序遍歷
	 */
	public void preOrder() {
		if (root != null) {
			 preOrderDetail(root);
		}
	}
	public void preOrderDetail(AVLNode node) {
		if (node != null) {
			System.out.print(node.data);
			System.out.print(" ");
			preOrderDetail(node.left);
			preOrderDetail(node.right);
		}
	}	
}

 

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