您的位置:首页 > 其它

avl平衡树

2018-03-26 21:09 399 查看
package com.algorithm.charactor1;

/**
* 在前面二叉查找树的基础上改的。。。。。
*
* 平衡avl树
*
* 注意:高度是指节点到 叶子的路径长
*
* 有四种可能,
* 1,在节点X的左节点的左子树上插入值,导致节点X,不满足 左右子树的高度差1
* 2,在节点X的右节点的右子树上插入值,导致节点X,不满足 左右子树的高度差1
* 1和2是 同一种对称情形,通过单旋转来达到平衡
*
* 3,在节点X的左节点的右子树上插入值,导致节点X,不满足 左右子树的高度差1
* 4,在节点X的右节点的左子树上插入值,导致节点X,不满足 左右子树的高度差1
* 3和4是 同一种对称情形,需要通过双旋转来使树达到平衡
*/

public class AVLTree<Element extends Comparable<? super Element>> {

//根节点
private AVLNode<Element> root;

//移除一个元素
public void remove(Element element){
root = remove(element,root);
}

/**
* 移除一个节点 分三种情况,
* 一个是 该节点本身是叶子,
* 一个是 该节点含有一个儿子节点
* 一个是 该节点还有两个儿子节点
* @param e
* @param comareElement
*/
private AVLNode<Element> remove(Element e, AVLNode<Element> comareElement) {
if (comareElement == null) {
return comareElement;
}

int compareTo = e.compareTo(comareElement.element);//要删除的元素 和当前元素进行比较

if (compareTo == 1) {//说明要删除的元素 在当前节点 的右边
comareElement.right = remove(e, comareElement.right); //等式的左边保留的是当前比较节点的父节点的引用
}else if (compareTo == -1) {//说明要删除的元素 在当前节点 的左边
comareElement.left = remove(e, comareElement.left);   //等式的左边保留的是当前比较节点的父节点的引用
}else if (compareTo == 0) {
//当要删除的节点是叶子的时候 直接置为null
if (comareElement.left == null  &&  comareElement.right == null) {
comareElement = null;
} else if (comareElement.left == null) {
//要删除的节点的左子节点为空的情况
comareElement = comareElement.right;
}else if (comareElement.right == null){
//要删除的节点的右子节点为空的情况
comareElement = comareElement.left;
}else {
//要删除的节点的 左右儿子节点都不为空的情况。	删除的节点 用右子树中最小节点替代,当然也可以用其他节点替代
AVLNode<Element>	min = findMin(comareElement);//右子树中最小节点
Element element =  min.element;//右子树中的元素
comareElement.element = element;//将右子树的值赋值给,当前找到元素的值。
comareElement.right = remove(element, comareElement.right);//将最小节点删掉

}

}
return balance(comareElement);
}

private AVLNode<Element>  findMin(AVLNode<Element> element){//查找并返回一个输入元素 最小子节点
if (element == null) {
return null;
}else if (element.left == null) {//左节点无值,说明该节点就是最小值
return element;
}else if (element.left != null) {
return findMin(element.left);
}
return null;
}

//插入一个元素
public void insert(Element element){

root = insert(element,root);
}

private AVLNode<Element> insert(Element e, AVLNode<Element> comareElement) {

if (comareElement == null) {//根节点无值,或者当前节点无值,说明要插入
comareElement = new AVLNode<Element>(e,null,null);
return comareElement;
}

int compareTo = e.compareTo(comareElement.element);//要查找的元素 和当前元素进行比较

if (compareTo == 1) {//说明要插入的值要 在当前比较节点的右边
comareElement.right = insert(e, comareElement.right);
}else if (compareTo == -1) {//说明要插入的值 在当前比较节点的左边
comareElement.left = insert(e, comareElement.left);
}else if (compareTo == 0 ) {//说明当前 插入的值存在
//			return null;
}
return balance(comareElement);
}

/**
* 左左情形 右旋转
* 		x
*     c d
*    b y
*   a
*
*   x为失衡节点, x的左儿子的左子树 添加了一个节点导致x失衡
* @param x
* @return
*/
private AVLNode<Element> rotateLeft(AVLNode<Element> x){
AVLNode<Element> c = 	x.left;
x.left = c.right;
c.right = x ;
x.height = Math.max(height(x.left), height(x.right)) + 1 ;
c.height = Math.max(height(c.left), x.height) + 1 ;
return c;
}

/**
* 字母都是随机的,不按照字母表排序
* 右右情形 ,左旋转
*		x
*    a   y
*      d   z
*            c
* x为失衡点 在x的右儿子的 右字数中 添加 ,导致x失衡
*
*/
private AVLNode<Element> rotateRight(AVLNode<Element> x){
AVLNode<Element> y = x.right;
x.right = y.left;
y.left = x;
x.height = Math.max(height(x.left), height(x.right)) + 1 ;
y.height = Math.max(height(y.left), x.height) + 1 ;
return y;
}

/**
* x为失衡点
* x的左儿子的 右子树中 ,添加一个 导致x失衡
*
*         x                             x                         y
*      w     d        左旋转                              y  d       右旋转                       w    x
*    a   y
a79c
----->         w  c        ------>      a     c  d
*      b   c                       a  b
*/

private AVLNode<Element> rotateLeftAndRight(AVLNode<Element> x){
x.left =  rotateRight(x.left);//先对x.left进行左旋转 ,
AVLNode<Element> y = rotateLeft(x);//对x进行右旋转
return y;
}

/**
* x为失衡点
* x的右儿子的 左子树中,添加一个 导致x失衡的情况
* 先进行右旋转, 后进行左旋转
*/

private AVLNode<Element> rotateRightAndLeft(AVLNode<Element> x){
x.right =  rotateLeft(x.right);//对x的有节点先进行右旋转
AVLNode<Element> y = rotateRight(x);//然后对x节点进行左旋转;
return y;
}

/**
* 节点插入后 要进行平衡操作。
* @param comareElement
* @return
*/
private AVLNode<Element> balance(AVLNode<Element> comareElement) {
if (comareElement == null) {
return null;
}

if (height(comareElement.left) - height(comareElement.right) >1) {//说明有需要进行平衡的节点
if (height(comareElement.left.left) >= height(comareElement.left.right)) {//说明左左 需要就行右旋转
comareElement = rotateLeft(comareElement);
}else {
comareElement = rotateLeftAndRight(comareElement);//先左旋转 后右旋转
}
}else if(height(comareElement.right) - height(comareElement.left) >1) {
if (height(comareElement.right.right) >= height(comareElement.right.left)) {//右右 需要进行做旋转
comareElement = rotateRight(comareElement);
}else {
comareElement = rotateRightAndLeft(comareElement);//先有旋转 后做旋转
}
}
comareElement.height = Math.max(height(comareElement.left), height(comareElement.right))+1;

return comareElement;
}

/**
* 返回节点的 高度
* @param node
* @return
*/
private Integer height(AVLNode<Element> node){
return node == null ? -1:node.height;
}

//是否包含某一个元素
public Boolean contains(Element element){

return contains(element,root);
}

private Boolean contains(Element e, AVLNode<Element> comareElement) {
if (comareElement == null) {
return false;
}

int compareTo = e.compareTo(comareElement.element);//要查找的元素 和当前元素进行比较

if (compareTo == 1) {//说明在右边
return contains(e, comareElement.right);//进行递归
}else if (compareTo == -1) {//说明在左边
return  contains(e, comareElement.left);
}

return true; //说明找到了当前节点
}

//节点的 左节点小 右节点大
private static class  AVLNode<Element>{ //一个二叉树节点
private Element element;
private AVLNode<Element> left;
private AVLNode<Element> right;
private Integer height =0;//相较于二叉查找树,新增对各节点 高度的值,用于计算是否平衡
public AVLNode(Element element, AVLNode<Element> left, AVLNode<Element> right, Integer height) {
super();
this.element = element;
this.left = left;
this.right = right;
this.height = height;
}
public AVLNode(Element element, AVLNode<Element> left, AVLNode<Element> right) {
super();
this.element = element;
this.left = left;
this.right = right;
}

}

public static void main(String[] args) {
AVLTree<Integer> binaryTree = new AVLTree<Integer>();
binaryTree.insert(6);
binaryTree.insert(2);
binaryTree.insert(8);
binaryTree.insert(1);
binaryTree.remove(2);
print(binaryTree.root);
}

static void print( AVLNode<Integer>  node){
if (node!=null) {
if (node.right!=null) {
print(node.right);
System.out.println(node.right.element);
}

if (node.left!=null) {
print(node.left);
System.out.println(node.left.element);
}
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: