一 .基本思想
1. AVL树是高度平衡的二叉树,满足左子树树上所有节点的值均小于根节点的值,右子树上所有节点的值均大于根节点的值,它的左右子树也分别为二叉搜索树
2.AVL树性质
(1)左子树和右子树高度之差绝对值不超过1
(2)树中每个左子树和右子树都是AVL树
(3)任何一个节点的平衡因子(BF)是 -1,0-1之一
二.AVL树的调整(LL RR LR RL)
传送门:https://blog.csdn.net/qq_34645958/article/details/80722625
三.AVL树的实现
1.创建节点类
public class AVLEntry<K,V> implements Map.Entry<K, V>{
//实现Map.Entry接口的getKey,getValue,setValue
public K key;
public V value;
public AVLEntry<K, V> left;
public AVLEntry<K, V> right;
public int height=1;
@Override
public K getKey() {
return key;
}
@Override
public V getValue() {
return value;
}
@Override
public V setValue(V value) {
this.value=value;
return value;
}
....带一个参数 两个参数 四个参数的构造函数
@Override
public String toString() {
return "AVLEntry [key=" + key + ", value=" + value + ", height="
+ height + "]";
}
}
2.插入
public class AVLMap<K, V> implements Iterable<AVLEntry<K, V>>{
private int size;
private AVLEntry<K, V> root;
private Comparator<K> comp;
private LinkedList<AVLEntry<K, V>> stack=new LinkedList<AVLEntry<K,V>>();
@SuppressWarnings("unchecked")
private int compare(K a, K b) {
if (comp != null) {
return comp.compare(a, b);
} else {
Comparable<K> c = (Comparable<K>) a;
return c.compareTo(b);
}
}
public AVLMap(Comparator<K> comp) {
super();
this.comp = comp;
}
public AVLMap() {
super();
}
public int size() {
return size;
}
//判断map是否为空
public boolean isEmpty() {
return size == 0 ? true : false;
}
//添加节点的方法
public V put(K key,V value){
//根节点为空直接插入
if(root==null){
root=new AVLEntry<K,V>(key, value);
stack.push(root);
size++;
}else{
AVLEntry<K,V> p=root;
while(p!=null){
stack.push(p);
int compareResult=compare(key, p.key);
//值相等,直接用新的value覆盖旧的value
if(compareResult==0){
p.setValue(value);
break;
//小于0 直接插入到左子树
}else if(compareResult<0){
//如果没有左子树直接插入新的节点
if(p.left==null){
p.left=new AVLEntry<K,V>(key, value);
size++;
stack.push(p.left);
break;
//大于0,直接插入到右子树
}else{
p=p.left;
}
//小于0 直接插入到左子树
}else{
if(p.right==null){
p.right=new AVLEntry<K,V>(key, value);
size++;
stack.push(p.right);
break;
}else{
p=p.right;
}
}
}
}
fixAfterInsertion(key);
return value;
}
//迭代方法
@Override
public Iterator<AVLEntry<K, V>> iterator() {
return new AVLIterator<K, V>(root);
}
}
插入后的平衡
//获取该节点高度
public int getHeight(AVLEntry<K, V> p){
return p==null?0:p.height;
}
private AVLEntry<K, V> rotateRight(AVLEntry<K, V> p){
AVLEntry<K, V> left=p.left;
p.left=left.right;
left.right=p;
p.height=Math.max(getHeight(p.left), getHeight(p.right))+1;
left.height=Math.max(getHeight(left.left), p.height)+1;
return left;
}
//左旋操作
private AVLEntry<K, V> rotateLeft(AVLEntry<K, V> p){
AVLEntry<K, V> right=p.right;
p.right=right.left;
right.left=p;
p.height=Math.max(getHeight(p.left), getHeight(p.right))+1;
right.height=Math.max(p.height, getHeight(right.right))+1;
return right;
}
//先左旋后右旋
private AVLEntry<K, V> firstLeftThenRight(AVLEntry<K, V> p){
p.left=rotateLeft(p.left);
p=rotateRight(p);
return p;
}
//先右旋后左旋
private AVLEntry<K, V> firstRightThenLeft(AVLEntry<K, V> p){
p.right=rotateRight(p.right);
p=rotateLeft(p);
return p;
}
//插入后调整成平衡树
private void fixAfterInsertion(K key){
AVLEntry<K, V> p=root;
while(!stack.isEmpty()){
p=stack.pop();
int newHeight=Math.max(getHeight(p.left), getHeight(p.right))+1;
if(p.height>1&&newHeight==p.height){
stack.clear();
return;
}
p.height=newHeight;
int d=getHeight(p.left)-getHeight(p.right);
if(Math.abs(d)<=1){
continue;
}else{
if(d==2){
if(compare(key, p.left.key)<0){
p=rotateRight(p);
}else{
p=firstLeftThenRight(p);
}
}else{
if(compare(key, p.right.key)>0){
p=rotateLeft(p);
}else{
p=firstRightThenLeft(p);
}
}
if(!stack.isEmpty()){
if(compare(key, stack.peek().key)<0){
stack.peek().left=p;
}else{
stack.peek().right=p;
}
}
}
}
root=p;
}
3.迭代器(中序遍历)
//中序遍历(非递归)
public class AVLIterator<K,V> implements Iterator<AVLEntry<K, V>>{
//栈
private Stack<AVLEntry<K, V>> stack;
//构造函数
public AVLIterator(AVLEntry<K, V> root) {
super();
stack=new Stack<AVLEntry<K,V>>();
addLeftPath(root);
}
//左路径节点压栈
private void addLeftPath(AVLEntry<K, V> p){
while(p!=null){
stack.push(p);
p=p.left;
}
}
@Override
public boolean hasNext() {
return stack.isEmpty()?false:true;
}
@Override
public AVLEntry<K, V> next() {
//弹出栈顶元素
AVLEntry<K, V> p=stack.pop();
//处理P的右子树
addLeftPath(p.right);
return p;
}
@Override
public void remove() {
throw new ConcurrentModificationException("Can not remove!");
}
}
4.查找(获得value,是否包含key)
private AVLEntry<K, V> getEntry(K key){
AVLEntry<K, V> p=root;
while(p!=null){
int compareResult=compare(key, p.key);
if(compareResult==0){
return p;
}else if(compareResult<0){
p=p.left;
}else{
p=p.right;
}
}
return null;
}
public boolean containsKey(K key){
AVLEntry<K, V> p=getEntry(key);
return p!=null;
}
public V get(K key){
AVLEntry<K, V> p=getEntry(key);
return p!=null?p.getValue():null;
}
public boolean containsValue(V value){
Iterator<AVLEntry<K, V>> itr=this.iterator();
while(itr.hasNext()){
if(itr.next().getValue().equals(value)){
return true;
}
}
return false;
}
5.删除
分三种情况:
(1)p是叶子节点,直接删除
(2)p只有左子树(或右子树),直接用p.left代替p
(3)p既有左子树,又有右子树,找到右子树的最小节点。用最小值替换p
public AVLEntry<K, V> getFirstEntry(AVLEntry<K, V> p){
if(p==null){
return null;
}
while(p.left!=null){
p=p.left;
}
return p;
}
public AVLEntry<K, V> getLastEntry(AVLEntry<K, V> p){
if(p==null){
return null;
}
while(p.right!=null){
p=p.right;
}
return p;
}
private AVLEntry<K, V> deleteEntry(AVLEntry<K, V> p,K key){
if(p==null){
return null;
}else{
int compareResult=compare(key, p.key);
if(compareResult==0){
//叶子节点直接删除
if(p.left==null&&p.right==null){
p=null;
//只有一个孩子,直接拿孩子替换该节点
}else if(p.left!=null&&p.right==null){
p=p.left;
}else if(p.left==null&&p.right!=null){
p=p.right;
}else{
if((size&1)==0){
AVLEntry<K, V> rightMin=getFirstEntry(p.right);
p.key=rightMin.key;
p.value=rightMin.value;
AVLEntry<K, V> newRight=deleteEntry(p.right, p.key);
p.right=newRight;
}else{
AVLEntry<K, V> leftMax=getLastEntry(p.left);
p.key=leftMax.key;
p.value=leftMax.value;
AVLEntry<K, V> newLeft=deleteEntry(p.left, p.key);
p.left=newLeft;
}
}
}else if(compareResult<0){
AVLEntry<K, V> newLeft=deleteEntry(p.left, key);
p.left=newLeft;
}else{
AVLEntry<K, V> newRight=deleteEntry(p.right, key);
p.right=newRight;
}
p=fixAfterDeletion(p);
return p;
}
}
public V remove(K key){
AVLEntry<K, V> entry=getEntry(key);
if(entry==null){
return null;
}
V oldValue=entry.getValue();
root=deleteEntry(root, key);
size--;
return oldValue;
}
删除后调整平衡
public AVLEntry<K, V> fixAfterDeletion(AVLEntry<K, V> p){
if(p==null){
return null;
}else{
p.height=Math.max(getHeight(p.left), getHeight(p.right))+1;
int d=getHeight(p.left)-getHeight(p.right);
if(d==2){
if(getHeight(p.left.left)-getHeight(p.left.right)>=0){
p=rotateRight(p);
}else{
p=firstLeftThenRight(p);
}
}else if(d==-2){
if(getHeight(p.right.right)-getHeight(p.right.left)>=0){
p=rotateLeft(p);
}else{
p=firstRightThenLeft(p);
}
}
return p;
}
}