数据结构--AVL树(六)

以下是学习恋上数据结构与算法的记录,本篇主要内容是二叉搜索树

◼平衡二叉搜索树(Balanced Binary Search Tree)

●二叉搜索树的复杂度分析
添加、删除节点时,都可能会导致二叉搜索树退化成链表
在这里插入图片描述●平衡(Balance)
在这里插入图片描述
●如何改进二叉搜索树?
◼首先,节点的添加、删除顺序是无法限制的,可以认为是随机的
◼所以,改进方案是:在节点的添加、删除操作之后,想办法让二叉搜索树恢复平衡(减小树的高度)
◼如果接着继续调整节点的位置,完全可以达到理想平衡,但是付出的代价可能会比较大,比如调整的次数会比较多,反而增加了时间复杂度
◼总结来说,比较合理的改进方案是:用尽量少的调整次数达到适度平衡即可
◼一棵达到适度平衡的二叉搜索树,可以称之为:平衡二叉搜索树
◼经典常见的平衡二叉搜索树有

AVL树

✓WindowsNT 内核中广泛使用

红黑树

C++STL(比如map、set )Java 的TreeMap、TreeSet、HashMap、HashSet 、Linux 的进程调度、 Ngix 的timer 管理
●一般也称它们为:自平衡的二叉搜索(SelfbalancingBinarySearchTree)


◼AVL树

◼平衡因子(Balance Factor):某结点的左右子树的高度差
◼AVL树的特点:每个节点的平衡因子只可能是1、0、-1(绝对值≤ 1,如果超过1,称之为“失衡”)
●每个节点的左右子树高度差不超过1
●搜索、添加、删除的时间复杂度是O(logn)
在这里插入图片描述接口简单设计
在这里插入图片描述
◼添加导致的失衡
●添加:只要让高度最低的失衡节点恢复平衡,整棵树就恢复平衡【仅需O(1) 次调整】
在这里插入图片描述

private boolean isBalanced(Node<E> node) {
		return Math.abs(((AVLNode<E>)node).balanceFactor()) <= 1;
	}
protected void afterAdd(Node<E> node) {
		while(node.parent!=null) {
			if(isBalanced(node)) {
				//更新高度
				updateHeight(node);
			}else {
				//恢复平衡
				rebalance(node);
				// 整棵树恢复平衡
				break;
			}
		}
	}

◼删除导致的失衡
●删除:恢复平衡后,可能会导致更高层的祖先节点失衡,最多需要O(logn) 次调整
在这里插入图片描述

protected void afterRemove(Node<E> node) {
		while(node.parent!=null) {
			if(isBalanced(node)) {
				//更新高度
				updateHeight(node);
			}else {
				//恢复平衡
				rebalance(node);
			}
		}
	}

●LL–右旋转(单旋)
LL情况:当前n节点是祖父节点的左子树的左子树时,就是左左。
则右旋转使其平衡,
具体为:祖父节点g指向父节点p的右子树,并父节点p成为这颗子树的根节点,祖父节点g成为父节点p的子树,更改的只有红线部分。
在这里插入图片描述

 private void rotateRight(Node<E> grand) {
    	//交换子树
    	Node<E> parent = grand.left;
		Node<E> child = parent.right;
		grand.left = child;
		parent.right = grand;
		//维护parent和hegiht
		afterRotate(grand, parent, child);
		}

●RR –左旋转(单旋)
RR情况:当前n节点是祖父节点的右子树的右子树时,就是右右。
则左旋转使其平衡。
具体为:祖父节点g指向父节点p的左子树,并父节点p成为这颗子树的根节点,祖父节点g成为父节点p的子树,更改的只有红线部分。
在这里插入图片描述

private void rotateLeft(Node<E> grand) {
		//交换子树
		Node<E> parent = grand.right;
		Node<E> child = parent.left;
		grand.right=child;
		parent.left=grand;
		//维护parent和hegiht
		afterRotate(grand, parent, child);
	}
	private void afterRotate(Node<E> grand, Node<E> parent, Node<E> child) {
		// 让parent称为子树的根节点
		parent.parent=grand.parent;
		if(grand.isLeftChild()) {
			grand.parent.left=parent;
		}else if (grand.isRightChild()) {
			grand.parent.right = parent;
		} else { // grand是root节点
			root = parent;
		}
		// 更新child的parent
		if (child != null) {
			child.parent = grand;
		}
		// 更新grand的parent
			grand.parent = parent;
		// 更新高度
			updateHeight(grand);
			updateHeight(parent);
	}

●LR –RR左旋转,LL右旋转(双旋)
父节点P先左旋转,然后祖父节点G右旋转
在这里插入图片描述●RL –LL右旋转,RR左旋转(双旋)
父节点p先右旋转,然后祖父节点g左旋转
在这里插入图片描述

private void rebalance(Node<E> grand) {
		Node<E> parent = ((AVLNode<E>)grand).tallerChild();
		Node<E> node = ((AVLNode<E>)parent).tallerChild();
		if(parent.isLeftChild()) {//L
			if(node.isLeftChild()) {//LL
				rotateRight(grand);
			}else {//LR
				rotateRight(parent);
				rotateLeft(grand);
			}
		}else {//R
			if(node.isLeftChild()) {//RL
				rotateRight(parent);
				rotateLeft(grand);
			}else {//RR
				rotateLeft(grand);
			}
		}
	}

◼独立出AVLNode在这里插入图片描述

private static class AVLNode<E> extends Node<E> {
        int height = 1;
		public AVLNode(E element, Node<E> parent) {
			super(element, parent);
			// TODO Auto-generated constructor stub
		}
		//平衡因子
		public int balanceFactor() {
			int leftheight = left ==null ? 0:((AVLNode<E>)left).height;
			int rightheight = left ==null ? 0:((AVLNode<E>)right).height;
			return leftheight-rightheight;
		}
		//更新高度
		public void updateHeight() {
			int leftheight = left ==null ? 0:((AVLNode<E>)left).height;
			int rightheight = left ==null ? 0:((AVLNode<E>)right).height;
			height=1+Math.max(leftheight, rightheight);
		}
		//判断左右子树
		public Node<E> tallerChild() {
			int leftheight = left ==null ? 0:((AVLNode<E>)left).height;
			int rightheight = left ==null ? 0:((AVLNode<E>)right).height;
			if (leftheight > rightheight) return left;
			if (leftheight < rightheight) return right;
			return  isLeftChild()  ? left : right;
		}
        @Override
		public String toString() {
			String parentString = "null";
			if (parent != null) {
				parentString = parent.element.toString();
			}
			return element + "_p(" + parentString + ")_h(" + height + ")";
		}
		
	}

◼平均时间复杂度:搜索:O(logn)、添加:O(logn),仅需O(1) 次的旋转操作,删除:O(logn),最多需要O(logn) 次的旋转操作。

猜你喜欢

转载自blog.csdn.net/qq_44961149/article/details/104657148