查找算法(4)平衡二叉树(AVL)

一 .基本思想

     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;
		}
	}


猜你喜欢

转载自blog.csdn.net/qq_34645958/article/details/80782745
今日推荐