AVL树

在AVL树中,任一节点对应的两棵子树的最大高度差为1,因此它也被称为高度平衡树。

查找、插入和删除在平均和最坏情况下的时间复杂度都是O(log n)。

增加和删除元素的操作则可能需要借由一次或多次树旋转,以实现树的重新平衡。

import java.util.LinkedList;
import java.util.Queue;

public class MyAVLTree {
	private class AVLNode {

		public AVLNode parent;
		public AVLNode leftChild, rightChild;
		public int data;
		
		public AVLNode(AVLNode parent, AVLNode leftChild, AVLNode rightChild, int data) {
			this.parent = parent;
			this.leftChild = leftChild;
			this.rightChild = rightChild;
			this.data = data;
		}
		
		public AVLNode(int data) {
			this(null, null, null, data);
		}
		
		public AVLNode(AVLNode parent, int data) {
			this.parent = parent;
			this.data = data;
		}
	}
	
	private AVLNode root;
	private final int LEFT = 1;
	private final int RIGHT = -1;
	private final int MAX_LEFT = 2;
	private final int MAX_RIGHT = -2;
	
	/**
	 * 插入节点
	 * @param data
	 */
	public void put(int data) {
		putData(root, data);
	}
	
	private boolean putData(AVLNode node, int data) {
		if(node == null) {
			node  = new AVLNode(data);
			root = node;
			return true;
		}
		int t;
		AVLNode p;
		AVLNode temp = node;
		do {
			p = temp;
			t = temp.data - data;
			if(t < 0) {
				temp = temp.rightChild;
			}
			else if(t > 0) {
				temp = temp.leftChild;
			}
			else {
				return false;
			}
		} while(temp != null);
		
		if(t < 0) {
			p.rightChild = new AVLNode(p, data);
		}
		else if(t > 0) {
			p.leftChild = new AVLNode(p, data);
		}
		rebuild(p);
		return true;
		
	}
	
	/**
	 * 平衡二叉树的方法
	 * @param node
	 */
	public void rebuild(AVLNode node) {
		while(node != null) {
			if(calcNodeBalanceValue(node) == MAX_LEFT) {
				fixAfterInsertion(node, LEFT);
			}
			else if(calcNodeBalanceValue(node) == MAX_RIGHT) {
				fixAfterInsertion(node, RIGHT);
			}
			node = node.parent;
		}
	}
	
	
	/**
	 * 调整树的结构
	 * @param node
	 * @param type
	 */
	public void fixAfterInsertion(AVLNode node, int type) {
		if(type == LEFT) {
			AVLNode leftChild = node.leftChild;
			if(leftChild.leftChild != null) {  //右旋
				rightRotation(node);
			}
			else if(leftChild.rightChild != null) {   //左右旋
				leftRotation(leftChild);
				rightRotation(node);
			}
		}
		else if(type == RIGHT) {
			AVLNode rightChild = node.rightChild;
			if(rightChild.rightChild != null) {   //左旋
				leftRotation(node);
			}
			else if(rightChild.leftChild != null) {   //右左旋
				rightRotation(rightChild);
				leftRotation(node);
			}
		}
	}
	
	
	/**
	 * 右旋
	 * @param node
	 * @return
	 */
	public AVLNode rightRotation(AVLNode node) {
		if(node != null) {
			
			AVLNode leftChild = node.leftChild;
			node.leftChild = leftChild.rightChild;
			// 如果leftChild的右节点存在,则需将该右节点的父节点指给node节点
			if(leftChild.rightChild != null) {  
				leftChild.rightChild.parent = node;
			}
			leftChild.parent = node.parent;
			if(node.parent == null) {
				this.root = leftChild;
			}
			else if(node.parent.rightChild == node) {  // 即node节点在它原父节点的右子树中
				node.parent.rightChild = leftChild;
			}
			else if(node.parent.leftChild == node) {
				node.parent.leftChild = leftChild;
			}
			
			leftChild.rightChild = node;
			node.parent = leftChild;
			return leftChild;
		}
		
		return null;
	}
	
	/**
	 * 左旋
	 * @param node
	 * @return
	 */
	public AVLNode leftRotation(AVLNode node) {
		
		if(node != null) {
			AVLNode rightChild = node.rightChild;
			node.rightChild = rightChild.leftChild;
			if(rightChild.leftChild != null) {
				rightChild.leftChild.parent = node;
			}
			rightChild.parent = node.parent;
			if(node.parent == null) {
				this.root = rightChild;
			}
			else if(node.parent.rightChild == node) {
				node.parent.rightChild = rightChild;
			}
			else if(node.parent.leftChild == node) {
				node.parent.leftChild = rightChild;
			}
			rightChild.leftChild = node;
			node.parent = rightChild;
			return rightChild;
		}
		
		return null;
	}
	
	/**
	 * 计算node节点的BF值
	 * @param node
	 * @return
	 */
	public int calcNodeBalanceValue(AVLNode node) {
		if(node != null) {
			return getHeightByNode(node);
		}
		return 0;
	}
	
	private int getHeightByNode(AVLNode node) {
		if(node == null) {
			return 0;
		}
		return getChildDepth(node.leftChild) - getChildDepth(node.rightChild);
	}
	
	private int getChildDepth(AVLNode node) {
		if(node == null) {
			return 0;
		}
		return 1 + Math.max(getChildDepth(node.leftChild), getChildDepth(node.rightChild));
	}
	
	
	/**
	 * 中序遍历
	 */
	public void middOrderErgodic() {
		this.middOrderErgodic(this.root);
	}
	public void middOrderErgodic(AVLNode node) {
		if(node != null) {
			this.middOrderErgodic(node.leftChild);
			System.out.print(node.data + ", ");
			this.middOrderErgodic(node.rightChild);
		}
	}
	
	
	/**
	 * 删除指定val值的节点
	 * @param val
	 * @return
	 */
	public boolean delete(int val) {
		AVLNode node = getNode(val);
		if(node == null) {
			return false;
		}
		boolean flag = false;
		AVLNode p = null;
		AVLNode parent = node.parent;
		AVLNode leftChild = node.leftChild;
		AVLNode rightChild = node.rightChild;
		if(leftChild == null && rightChild == null) {
			if(parent != null) {
				if(parent.leftChild == node) {
					parent.leftChild = null;
				}
				else if(parent.rightChild == node) {
					parent.rightChild = null;
				}
			}
			else {
				this.root = null;
			}
			
			p = parent;
			node = null;
			flag = true;
		}
		else if(leftChild == null && rightChild != null) {
			if(parent != null && parent.data > val) {
				parent.leftChild = rightChild;
			}
			else if(parent != null && parent.data < val) {
				parent.rightChild = rightChild;
			}
			else {
				this.root = rightChild;
			}
			p = parent;
			node = null;
			flag = true;
		}
		else if(leftChild != null && rightChild == null) {
			if(parent != null &&  parent.data > val) {
				parent.leftChild = leftChild;
			}
			else if(parent != null && parent.data < val) {
				parent.rightChild = leftChild;
			}
			else {
				this.root = leftChild;
			}
			
			p = parent;
			node = null;
			flag = true;
		}
		else if(leftChild != null && rightChild != null) {
			AVLNode successor = getSuccessor(node);
			int tempData = successor.data;
			if(delete(tempData)) {
				node.data = tempData;
			}
			p = successor;
			successor = null;
			flag = true;
		}
		
		if(flag) {
			this.rebuild(p);
		}
		return flag;	
	}
	
	
	/**
	 * 获得指定节点
	 * @param key
	 * @return
	 */
	public AVLNode getNode(int key) {
	
		AVLNode node = root;
		int t;
		do {
			t = node.data - key;
			if(t > 0) {
				node = node.leftChild;
			}
			else if(t < 0) {
				node = node.rightChild;
			}
			else {
				return node;
			}
		} while(node != null);
		return null;
	}
	
	
	/***
	 * 获得指定节点的后继
	 * 找到node节点的后继节点
     * 1、先判断该节点有没有右子树,如果有,则从右节点的左子树中寻找后继节点,没有则进行下一步
     * 2、查找该节点的父节点,若该父节点的右节点等于该节点,则继续寻找父节点,
     *   直至父节点为Null或找到不等于该节点的右节点。
     * 理由,后继节点一定比该节点大,若存在右子树,则后继节点一定存在右子树中,这是第一步的理由
     *      若不存在右子树,则也可能存在该节点的某个祖父节点(即该节点的父节点,或更上层父节点)的右子树中,
     *      对其迭代查找,若有,则返回该节点,没有则返回null
	 * @param node
	 * @return
	 */
	public AVLNode getSuccessor(AVLNode node) {
		if(node.rightChild != null) {
			AVLNode rightChild=  node.rightChild;
			while(rightChild.leftChild != null) {
				rightChild = rightChild.leftChild;
			}
			return rightChild;
		}
		AVLNode parent = node.parent;
		while(parent != null && (node == parent.rightChild)) {
			node = parent;
			parent = parent.parent;
		}
		return parent;
	}
	
	
	/**
	 * 层序遍历
	 */
	public void sequenceErgodic() {
		if(this.root == null) {
			return;
		}
		Queue<AVLNode> queue = new LinkedList<>();
		AVLNode temp = null;
		queue.add(this.root);
		while(!queue.isEmpty()) {
			temp = queue.poll();
			System.out.println("当前节点值:" + temp.data + ", BF:" + calcNodeBalanceValue(temp));
			if(temp.leftChild != null) {
				queue.add(temp.leftChild);
			}
			if(temp.rightChild != null) {
				queue.add(temp.rightChild);
			}
		}
	}
	
	public static void main(String[] args) {
		MyAVLTree bbt = new MyAVLTree();
        bbt.put(3);
        bbt.put(2);
        bbt.put(1);
        bbt.put(4);
        bbt.put(5);
        bbt.put(6);
        bbt.put(7);
        bbt.put(10);
        bbt.put(9);
        bbt.middOrderErgodic();
        System.out.println();
        System.out.println("-----各节点平衡状况-----");
        bbt.sequenceErgodic();
        System.out.println();
        bbt.delete(5);
        bbt.delete(2);
        bbt.middOrderErgodic();
        System.out.println();
        System.out.println("-----各节点平衡状况-----");
        bbt.sequenceErgodic();
        System.out.println();
        
	}
}

Last updated