JAVA代碼實現平衡二叉樹

平衡二叉樹

平衡二叉樹又叫AVL樹,它是在二叉排序樹的基礎上進行了樹結構的調整,使其根節點的左右子樹的高度差一致。可以保證查詢效率更加高效。
平衡二叉樹涉及到左旋轉、右旋轉和雙旋轉,接下來分別用圖解分析一下:

左旋轉

在這裏插入圖片描述

右旋轉

在這裏插入圖片描述

雙旋轉

在這裏插入圖片描述
代碼如下:

package com.avl;

/*
 * 平衡二叉樹:
 * 1.左旋轉
 * 2.右旋轉
 * 3.雙旋轉
 */
public class AVLTreeDemo2 {

	public static void main(String[] args) {
		int[] arr = { 4, 3, 6, 5, 7, 8 };// 左旋轉
		// int[] arr = { 10, 12, 8, 9, 7, 6 };// 右旋轉
		// int[] arr = { 10, 11, 7, 6, 8, 9 };// 雙旋轉
		AVLTree2 avlTree2 = new AVLTree2();
		for (int i = 0; i < arr.length; i++) {
			avlTree2.add(new Node2(arr[i]));
		}

		System.out.println("樹的高度=" + avlTree2.getRoot().height());
		System.out.println("左子樹的高度=" + avlTree2.getRoot().leftHeight());
		System.out.println("右子樹的高度=" + avlTree2.getRoot().rightHeight());
		System.out.println("前序遍歷");
		avlTree2.preList();
		System.out.println("中序遍歷");
		avlTree2.infixList();
	}

}

//創建平衡二叉樹
class AVLTree2 {
	Node2 root;

	public Node2 getRoot() {
		return root;
	}

	// 前序遍歷
	public void preList() {
		if (root == null) {
			System.out.println("空樹無法遍歷!");
			return;
		}
		root.preList();
	}

	// 中序遍歷
	public void infixList() {
		if (root == null) {
			System.out.println("空樹無法遍歷!");
			return;
		}
		root.infixList();
	}

	/**
	 * 添加節點
	 * 
	 * @param node
	 */
	public void add(Node2 node) {
		if (root == null) {
			root = node;
			return;
		}
		root.add(node);
	}
}

//創建節點類
class Node2 {
	int value;
	Node2 left;
	Node2 right;

	public Node2(int value) {
		this.value = value;
	}

	@Override
	public String toString() {
		return "Node2 [value=" + value + "]";
	}

	// 前序遍歷
	public void preList() {
		System.out.println(this);
		if (this.left != null) {
			this.left.preList();
		}
		if (this.right != null) {
			this.right.preList();
		}
	}

	// 中序遍歷
	public void infixList() {
		if (this.left != null) {
			this.left.infixList();
		}
		System.out.println(this);
		if (this.right != null) {
			this.right.infixList();
		}
	}

	// 以當前節點爲根節點,求其樹的高度
	public int height() {
		return Math.max(this.left == null ? 0 : this.left.height(), this.right == null ? 0 : this.right.height()) + 1;
	}

	// 求當前節點左子樹的高度
	public int leftHeight() {
		if (this.left == null) {
			return 0;
		}
		return this.left.height();

	}

	// 求當前節點右子樹的高度
	public int rightHeight() {
		if (this.right == null) {
			return 0;
		}
		return this.right.height();
	}

	/**
	 * 左旋轉
	 */
	public void leftRotate() {
		// 1.以當前節點爲根結點,創建一個新的節點,值爲當前節點的值
		Node2 newNode = new Node2(this.value);
		// 2.將新節點的左子節點設置成當前節點的左子樹
		newNode.left = this.left;
		// 3.將新節點的右子節點設置成當前節點右子節點的左子樹
		newNode.right = this.right.left;
		// 4.將當前節點的值替換成其右子節點的值
		this.value = this.right.value;
		// 5.將當前節點的右子節點設置成當前節點右子節點的右子樹
		this.right = this.right.right;
		// 6.將當前節點的左子節點設置成新節點
		this.left = newNode;
	}

	/**
	 * 右旋轉
	 */
	public void rightRotate() {
		// 1.以當前節點爲根節點,創建一個新的節點,值爲當前節點的值
		Node2 newNode = new Node2(this.value);
		// 2.將新節點的右子節點設置成當前節點的右子樹
		newNode.right = this.right;
		// 3.將新節點的左子節點設置成當前節點左子節點的右子樹
		newNode.left = this.left.right;
		// 4.將當前節點的值替換成其左子節點的值
		this.value = this.left.value;
		// 5.將當前節點的左子節點設置成當前節點左子節點的左子樹
		this.left = this.left.left;
		// 6.將當前節點的右子節點設置成新節點
		this.right = newNode;
	}

	/**
	 * 添加節點
	 * 
	 * @param node
	 */
	public void add(Node2 node) {
		if (node == null) {
			return;
		}
		// 如果要添加節點的值小於當前節點的值
		if (node.value < this.value) {
			// 如果當前節點的左子節點爲空,那就直接掛上
			if (this.left == null) {
				this.left = node;
			} else {// 如果不爲空,左遞歸
				this.left.add(node);
			}
		} else {// 如果要添加節點的值大於或等於當前節點的值
				// 如果當前節點的右子節點爲空,那就直接掛上
			if (this.right == null) {
				this.right = node;
			} else {// 如果不爲空,右遞歸
				this.right.add(node);
			}
		}

		// 節點添加完畢後,要開始判斷是否是平衡二叉樹,如果不是需要進行旋轉操作
		// 1.如果當前節點的左子樹高度-右子樹高度>1,那麼需要進行右旋轉
		if (this.leftHeight() - this.rightHeight() > 1) {
			// !!!這裏有種情況:如果以當前節點的左子節點爲根節點,其右子樹的高度>其左子樹的高度時,需要局部進行左旋轉。
			if (this.left != null && this.left.rightHeight() > this.left.leftHeight()) {
				// 以當前節點的左子節點爲根節點,進行局部左旋轉
				this.left.leftRotate();
			}
			// 然後以當前節點爲根節點,進行右旋轉
			this.rightRotate();
			// 旋轉完就可以退出了
			return;
		}

		// 2.如果當前節點的右子樹高度-左子樹高度>1,那麼需要進行左旋轉
		if (this.rightHeight() - this.leftHeight() > 1) {
			// !!!這裏有種情況:如果以當前節點的右子節點爲根節點,其左子樹的高度>其右子樹的高度時,需要進行局部右旋轉
			if (this.right != null && this.right.leftHeight() > this.right.rightHeight()) {
				// 以當前節點的右子節點爲根結點,進行局部右旋轉
				this.right.rightHeight();
			}
			// 然後以當前節點爲根結點,進行左旋轉
			this.leftRotate();
		}

	}

}

如有錯誤之處,還望指出,定會及時改正!

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