1. 程式人生 > >AVL樹簡介及Java實現

AVL樹簡介及Java實現

AVL樹簡介

AVL樹是被最先發明的一種較為簡單的平衡二叉查詢樹。

它的特點是:

1.本身首先是一棵二叉查詢樹。

2.帶有平衡條件:每個結點的左右子樹的高度之差的絕對值(平衡因子LoadFactor)最多為1。(設根結點的高度為1)

上面的兩張圖片,左邊的是AVL樹,它的任何節點的兩個子樹的高度差別都小於等於1;而右邊的不是AVL樹,因為結點7的兩顆子樹的高度相差為2(以2為根節點的樹的高度是3,而以8為根節點的樹的高度是1)。 

AVL樹的查詢、插入和刪除在平均和最壞情況下都是O(logn)。

在對AVL樹進行插入或刪除一個結點之後,會可能導致樹中某個結點的左右子樹的高度之差超過1,從而破壞了AVL樹的適度平衡。因此,為了讓它重新回到平衡狀態,需要採取額外的操作。

重平衡操作

在AVL樹中進行插入或者刪除一個結點之後,可能會導致AVL樹的失衡。AVL樹失衡的狀態一共可以分為以下四種:

 1、LL情況

如下圖所示,進行一次右旋轉RotateRight就可以恢復樹的平衡。

//LL情況
	private Node rotateRight(Node node) {
		Node temp = node.left;
		node.left = temp.right;
		temp.right = node;
		node.height = max(height(node.left), height(node.right)) + 1;
		temp.height = max(height(temp.left), height(temp.right)) + 1;
		return temp;
	}

2、RR情況

如下圖所示,進行一次左旋轉RotateLeft就可以恢復樹的平衡。

//RR情況
	private Node rotateLeft(Node node) {
		Node temp = node.right;
		node.right = temp.left;
		temp.left = node;
		node.height = max(height(node.left), height(node.right)) + 1;
		temp.height = max(height(temp.left), height(temp.right)) + 1;
		return temp;
	}

3、LR情況

如下圖所示,先對1結點進行一次左旋轉,再對3結點進行一次右旋轉就可以恢復樹的平衡。

//LR情況
	private Node LR(Node node) {
		node.left = rotateLeft(node.left);
		return rotateRight(node);
	}

 4、RL情況

如下圖所示,先對3結點進行一次右旋轉,再對1結點進行一次左旋轉就可以恢復樹的平衡。

//RL情況
	private Node RL(Node node) {
		node.right = rotateRight(node.right);
		return rotateLeft(node);
	}

 AVL樹完整Java實現


public class AVLTree<Key extends Comparable<Key>, Value> {
	
	private Node root;
	
	private class Node {
		Key key;
		Value val;
		int height;
		Node left,right;
		
		public Node(Key key, Value val, int height) {
			this.key = key;
			this.val = val;
			this.height = height;
		}
	}
	
	public void put(Key key, Value val) {
		root = put(root, key, val);
	}
	
	private Node put(Node node, Key key, Value val) {
		if(node == null)
			return new Node(key, val, 1);
		int cmp = key.compareTo(node.key);
		if(cmp > 0) {
			node.right = put(node.right, key, val);
			if(height(node.right) - height(node.left) == 2) {
				if(key.compareTo(node.right.key) > 0)
					node = rotateLeft(node);
				else
					node = RL(node);
			}
		} else if(cmp < 0) {
			node.left = put(node.left, key, val);
			if(height(node.left) - height(node.right) == 2) {
				if(key.compareTo(node.left.key) < 0)
					node = rotateRight(node);
				else
					node = LR(node);
			}
		} else {
			node.val = val;
		}
		node.height = max(height(node.left), height(node.right)) + 1;
		return node;
	}
	
	public Value delete(Key key) {
		Node node = delete(root, key);
		if(node == null)
			return null;
		return node.val;
	}
	
	private Node delete(Node node, Key key) {
		if(key == null || node == null)
			return null;
		return node;
	}
	
	//LL情況
	private Node rotateRight(Node node) {
		Node temp = node.left;
		node.left = temp.right;
		temp.right = node;
		node.height = max(height(node.left), height(node.right)) + 1;
		temp.height = max(height(temp.left), height(temp.right)) + 1;
		return temp;
	}
	
	//RR情況
	private Node rotateLeft(Node node) {
		Node temp = node.right;
		node.right = temp.left;
		temp.left = node;
		node.height = max(height(node.left), height(node.right)) + 1;
		temp.height = max(height(temp.left), height(temp.right)) + 1;
		return temp;
	}
	
	//LR情況
	private Node LR(Node node) {
		node.left = rotateLeft(node.left);
		return rotateRight(node);
	}
	
	//RL情況
	private Node RL(Node node) {
		node.right = rotateRight(node.right);
		return rotateLeft(node);
	}
	
	//以node為根結點的子樹的高度
	private int height(Node node) {
		if(node == null)
			return 0;
		return node.height;
	}
	
	private int max(int a, int b) {
		return a > b ? a : b;
	}
	
	

	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}

}