欢迎使用CSDN-markdown编辑器

来源:互联网 发布:seo搜索排名优化怎么 编辑:程序博客网 时间:2024/06/05 16:45

二叉平衡树

说起这个树,我找了整整两天的时间,刚开始考虑的不周全,然后就一直该一直该,一直加一直加。
定义:
它是一颗空疏或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一颗平衡二叉树。
二叉查找树的定义:
1、若左子树不为空,那么左子树所有结点的值小于均小于他的根结点的值
2、若右子树不为空,那么右子树的所有结点的值大于根结点的值
3、左右子树也分别为二叉查找树(排序树)
4、没有键值相当的结点
如果不知道二叉查找树了请看我上篇文章(格式不太好)
现在二叉查找树添加的源码:
在这里我定义了root,opRoot两个,root主要是根结点,方便以后去操作,opRoot主要是操作树的。

// 插入元素    public void insert(T t){        if(opRoot == null){            root.setT(t);            opRoot = root;            return ;        }        opRoot = root ;        Node<T> node = new Node<T>();        node.setT(t);        insert(opRoot , node) ;    }    // 插入值    private void insert(Node<T> opRoot, Node<T> node) {        if(opRoot.getT().compareTo(node.getT()) > 0){            if(opRoot.getLeft() != null){                insert(opRoot.getLeft() , node ) ;            }else {                opRoot.setLeft(node);                node.setParent(opRoot);            }        }        if(opRoot.getT().compareTo(node.getT()) < 0){            if(opRoot.getRight() != null){                insert(opRoot.getRight() , node) ;            }else {                opRoot.setRight(node);                node.setParent(opRoot);            }        }    }

值已经插进去了,现在我们要判断这四种情况:
1、 在结点x的左孩子的左子树中插入元素(左左)
2、 在结点x的左孩子的右子树中插入元素(左右)
3、 在结点x的右孩子的左子树中插入元素(右左)
4、 在结点x的右孩子的右子树中插入元素(右右)
括号里这些代表有,没写的代表下层没有
首先看第一种情况:
这里写图片描述
我是这样考虑的,换位置,把第一个左换到上面,然后把第一个上面的放到有下面,注意:需要断开的一定要断开。
第四种情况,有类似第一种:
这里写图片描述
类似于上面那种,也是交换位置
还有一个leftOrRight这个类

这里写图片描述

这里是段开父类之后,然后下面的那个元素指向父类元素
第二种左右,也是交换位置
这里写图片描述
把最上面的和最下面的交换位置就行,把4放到5的位置,把5放到4的右子树
这里写图片描述
第三种右左

这里写图片描述
这里写图片描述
把四和三交换位置,然后把3放到4的左子树
最后一个root.setParent(null),防止操作到根元素,忘记把根的父给清除了。
这里写图片描述
上面这段代码也是判断父类的到底该左子树设置还是右子树设置。
接下来,还要考虑这种:
这里写图片描述
左边是第一次按照上面那样插入,留下的病根,右边左转一次的情况,这里还有右转,直到达到预期效
下面代码弄了好多次都不型,只能这样了,作用是判断左右的深度差师傅大于1.
private void leftAndRightBalance(Node opRoot) {
int left = treeDepth(opRoot.getLeft()) ;
int right = treeDepth(opRoot.getRight()) ;
if(left - right > 1){
rightxuanzhuan(opRoot);
return ;
}
if(right - left > 1){
leftxuanzhuan(opRoot);
return ;
}
底下是右旋转旋转一次
// 这里是左旋转的
private void rightxuanzhuan(Node opRoot) {
Node parent = opRoot.getParent();
Node left = opRoot.getLeft();
Node right = opRoot.getRight();
Node rightLeft = findLeft(right);
if(rightLeft.getT().compareTo(right.getT()) == 0){
rightLeft = null ;
}
newxuanzhuan(rightLeft);
left.setParent(parent);
if(parent != null){
parent.setLeft(left);
}else {
root = left ;
left.setParent(null);
}
if(rightLeft != null){
rightLeft.setLeft(left.getLeft());
if(left.getLeft()!=null){
left.getLeft().setParent(rightLeft);
}
}else{
opRoot.setLeft(left.getRight());
if(left.getRight() != null){
left.getRight().setParent(opRoot);
}
}
left.setRight(opRoot);
zaipanduan(left)
左旋转一次
private void leftxuanzhuan(Node opRoot) {
Node parent = opRoot.getParent();
Node right = opRoot.getRight();
Node rightleft = findLeft(right);
newxuanzhuan(rightleft);
right.setParent(parent);
if(parent != null){
parent.setRight(right);
}else{
root = right;
}
if(rightleft != null){
rightleft.setLeft(opRoot);
opRoot.setParent(rightleft);
}else{
right.setLeft(opRoot);
opRoot.setParent(right);
}
opRoot.setRight(null);
zaipanduan(right);
}
// 为上面这两个类提供的旋转
private void newxuanzhuan(Node rightleft) {
if(rightleft == null){
return ;
}
Node parent = rightleft.getParent();
if(parent == null || parent.getRight() != null){
return ;
}
rightleft.setParent(parent.getParent());

if(parent.getParent().getLeft() != null && parent.getParent().getLeft().getT().compareTo(parent.getT()) == 0){        parent.getParent().setLeft(parent.getLeft());    }else{        parent.getParent().setRight(parent.getLeft());    }    rightleft.setRight(parent);    parent.setParent(rightleft);    parent.setLeft(null);}

作用是为上面两个方法提供旋转

下面这个是再进去,判断是否合理
private void zaipanduan(Node left) {
if(left != null && left.getLeft() != null){
zaipanduan(left.getLeft());
}
if(left !=null && left.getRight() != null){
zaipanduan(left.getRight());
}
zaipanduandigui(left);
}
private void zaipanduandigui(Node left){
xuanzhuanshu(left);
}

接下来给你们源码看,在这我建议你一步一步来,每一种你考虑考虑,然后把代码进一步优化
public void insert(T t) {
if (root.getT() == null) {
root.setT(t);
size++;
return;
}
opRoot = root;
Node node = new Node();
node.setT(t);
insert(opRoot, node);
size++;
}

private void insert(Node<T> opRoot, Node<T> node) {    if (opRoot.getT().compareTo(node.getT()) > 0) {        if (opRoot.getLeft() != null) {            insert(opRoot.getLeft(), node);        } else {            opRoot.setLeft(node);            node.setParent(opRoot);            xuanzhuanshu(node);        }    }    if (opRoot.getT().compareTo(node.getT()) < 0) {        if (opRoot.getRight() != null) {            insert(opRoot.getRight(), node);        } else {            opRoot.setRight(node);            node.setParent(opRoot);            xuanzhuanshu(node);        }    }}/* * 添加的时候有四种判断方式。 第一种是左左 第二种是右右 第三种是左右 第四种是右左 */private void xuanzhuanshu(Node<T> node) {    Node<T> parent = null;    // 判断,是否右父父(爷爷元素)    if (node.getParent() != null && node.getParent().getParent() != null)        parent = node.getParent().getParent();    if (parent == null) {        return;    }    // 连续左左为空,右右有元素    if (parent.getLeft() == null && node.getParent().getLeft() == null) {        if (parent.getParent() != null) {            leftOrRight(parent.getParent(), node.getParent());            node.getParent().setParent(parent.getParent());            node.getParent().setLeft(parent);        } else {            node.getParent().setLeft(parent);            root = node.getParent();        }        parent.setParent(node.getParent());        parent.setRight(null);    }    // 连续左左有元素,右右为空    if (parent.getRight() == null && node.getParent().getRight() == null) {        if (parent.getParent() != null) {            leftOrRight(parent.getParent(), node.getParent());            node.getParent().setParent(parent.getParent());            node.getParent().setRight(parent);        } else {            node.getParent().setRight(parent);            root = node.getParent();        }        parent.setParent(node.getParent());        parent.setLeft(null);    }    // 下面是右空,然后在左空    if (parent.getRight() == null && node.getParent().getLeft() == null) {        if (parent.getParent() != null) {            leftOrRightNoOnOne(parent.getParent(), node);            node.setParent(parent.getParent());            node.setLeft(parent.getLeft());            parent.getLeft().setParent(node);            parent.getLeft().setRight(null);            node.setRight(parent);            parent.setParent(node);            parent.setLeft(null);        } else {            root = node;            node.setRight(parent);            parent.setParent(node);            parent.setLeft(null);            node.setLeft(node.getParent());            node.getParent().setParent(node);            node.getParent().setRight(null);        }    }    // 左空,右空    if (parent.getLeft() == null && node.getParent().getRight() == null) {        if (parent.getParent() != null) {            leftOrRightNoOnOne(parent.getParent(), node);            node.setParent(parent.getParent());            node.setRight(parent.getRight());            parent.getRight().setParent(node);            parent.getRight().setLeft(null);            node.setLeft(parent);            parent.setParent(node);            parent.setRight(null);        } else {            root = node;            node.setLeft(parent);            parent.setParent(node);            parent.setRight(null);            node.setRight(node.getParent());            node.getParent().setParent(node);            node.getParent().setLeft(null);        }    }    root.setParent(null);    opRoot = root ;    leftAndRightBalance(opRoot);}// 这个是用来检查左右方法平衡不平衡,两边的深度差是否小于等于1,如果大于1了,根据方向旋转;private void leftAndRightBalance(Node<T> opRoot) {    int left = treeDepth(opRoot.getLeft()) ;    int right = treeDepth(opRoot.getRight()) ;    if(left - right > 1){        rightxuanzhuan(opRoot);        return ;    }    if(right - left > 1){        leftxuanzhuan(opRoot);        return ;    }}// 这里是左旋转的private void rightxuanzhuan(Node<T> opRoot) {    Node<T> parent = opRoot.getParent();    Node<T> left = opRoot.getLeft();    Node<T> right = opRoot.getRight();    Node<T> rightLeft = findLeft(right);    if(rightLeft.getT().compareTo(right.getT()) == 0){        rightLeft = null ;    }    newxuanzhuan(rightLeft);    left.setParent(parent);    if(parent != null){        parent.setLeft(left);    }else {        root = left ;        left.setParent(null);    }    if(rightLeft != null){        rightLeft.setLeft(left.getLeft());        if(left.getLeft()!=null){            left.getLeft().setParent(rightLeft);        }    }else{        opRoot.setLeft(left.getRight());        if(left.getRight() != null){            left.getRight().setParent(opRoot);        }    }    left.setRight(opRoot);    zaipanduan(left);}private void zaipanduan(Node<T> left) {    if(left != null && left.getLeft() != null){        zaipanduan(left.getLeft());    }    if(left !=null && left.getRight() != null){        zaipanduan(left.getRight());    }    zaipanduandigui(left);}private void zaipanduandigui(Node<T> left){    xuanzhuanshu(left);}private void leftxuanzhuan(Node<T> opRoot) {    Node<T> parent = opRoot.getParent();    Node<T> right = opRoot.getRight();    Node<T> rightleft = findLeft(right);    newxuanzhuan(rightleft);    right.setParent(parent);    if(parent != null){        parent.setRight(right);    }else{        root = right;    }    if(rightleft != null){        rightleft.setLeft(opRoot);        opRoot.setParent(rightleft);    }else{        right.setLeft(opRoot);        opRoot.setParent(right);    }    opRoot.setRight(null);    zaipanduan(right);}// 为上面这两个类提供的旋转private void newxuanzhuan(Node<T> rightleft) {    if(rightleft == null){        return ;    }    Node<T> parent = rightleft.getParent();    if(parent == null || parent.getRight() != null){        return ;    }    rightleft.setParent(parent.getParent());    if(parent.getParent().getLeft() != null && parent.getParent().getLeft().getT().compareTo(parent.getT()) == 0){        parent.getParent().setLeft(parent.getLeft());    }else{        parent.getParent().setRight(parent.getLeft());    }    rightleft.setRight(parent);    parent.setParent(rightleft);    parent.setLeft(null);}// 这个用于处理,不是连续的private void leftOrRightNoOnOne(Node<T> parent, Node<T> son) {    if (parent.getLeft().getT().compareTo(son.getParent().getParent().getT()) == 0) {        parent.setLeft(son);    } else {        parent.setRight(son);    }}// 处理连续的private void leftOrRight(Node<T> parent, Node<T> son) {    if (parent.getLeft() != null && parent.getLeft().getT()            .compareTo(son.getParent().getT()) == 0) {        parent.setLeft(son);    } else {        parent.setRight(son);    }}
原创粉丝点击