二叉查找树复习简记

remove

remove分成三种情况,没有孩子节点的节点(即页子),单个孩子节点的节点,两个孩子节点的节点

1)页子节点可以直接删除

2)单个孩子节点的节点删除了,让其下的孩子节点直接和其父亲节点相连(就是孩子节点和祖父节点相连)

3)两个孩子节点的节点,为了保持排序状态,需要拿到这个节点的左子树的最大节点或者右子树的最小节点,得到这个节点的数据代替要删除的节点,

然后删除这个左子树的最大节点或者右子树的最小节点,因为左子树的最大节点没有右节点(有右节点的话,他就不是最大的了),同理,右子树的最小节点

没有左节点,所以要删除的这个节点只有一个或者没有孩子节点,只需要进行1)或者2)就完成了。

 


AVL树


 

在插入节点时通过旋转(rotation)解决问题:

  /**
     * 插入一个元素到树里面,可能破坏了高度差,需要找到一个节点a,该节点左子树和右子树被破坏了,则需要对这个节点(平衡因子)
     * 
     * 树进行平衡,有四种情况:
     * 
     * 1.a节点的左儿子的左子树插入
     * 
     * 2.a节点的左儿子的右子树插入
     * 
     * 3.a节点的右儿子的左子树插入
     * 
     * 4.a节点的右儿子的右子树插入
     * 
     * 
     * 1.4两种情况需要进行一次旋转
     * 
     * 2.3两种情况需要进行两次旋转
     *
     * 旋转的目的是为了使插入节点的树的高度降低1,所以只要求旋转平衡因子为根的树就可以了
    
*/


在删除节点的时候:
    /**
     * 删除一个节点,找到平衡因子,他的左子树高度和右子树高度如果相差2的话,就需要旋转,而且旋转后,平衡因子的节点为根的树的高度肯定会
     * 
     * 下降1,这样平衡因子所在的树的高度下降1,也有可能需要进行旋转调整,这样调整一直到根节点
     * 
     
*/

代码如下:


package struct;


/**
 * 
@author chenxiaohui
 * 
@version 创建时间:2011-8-26
 * 
 * 
 
*/
public class AvlTree {
    
/**
     * 
     * avl树:树中每个节点的左子树和右子树的高度最多差1的二叉查找树
     * 
     * 
     * 
     
*/

    
public int height(AvlNode node) {
        
return node != null ? node.height : -1;
    }

    
/**
     * 
     * 
     * 插入一个元素到树里面,可能破坏了高度差,需要找到一个节点a,该节点左子树和右子树被破坏了,则需要对这个节点(平衡因子)
     * 
     * 树进行平衡,有四种情况:
     * 
     * 1.a节点的左儿子的左子树插入
     * 
     * 2.a节点的左儿子的右子树插入
     * 
     * 3.a节点的右儿子的左子树插入
     * 
     * 4.a节点的右儿子的右子树插入
     * 
     * 
     * 1.4两种情况需要进行一次旋转
     * 
     * 2.3两种情况需要进行两次旋转
     * 
     * 
@param t
     * 
@param tree
     * 
@return
     
*/

    
public AvlNode insert(int t, AvlNode tree) {

        
if (tree == null)
            
return new AvlNode(t);

        
int cmp = compare(t, tree.element);

        
if (cmp < 0) {
            
// 左子树
            tree.leftChild = insert(t, tree.leftChild);

            
// 因为左子树插入了节点,那么左子树比右子树高,根据avl树的性质,插入了节点
            
// 要么高度差为1,要么高度差为2,所以当相差为2时,需要进行树的调整
            if ((height(tree.leftChild) - height(tree.reightChild)) == 2) {

                
// 当t比树左子树的元素还小的话,就是在树的左子树的左边插入节点,成为左子树的左子树,需要一次旋转
                if (compare(t, tree.leftChild.element) < 0) {

                    tree 
= rotateLeftChild(tree);
                } 
else {
                    
// 当t比树左子树的元素还大的话,就是在树的左子树的右边插入节点,成为左子树的右子树,需要两次旋转
                    tree = doubleRotateLeftChild(tree);
                }
            }

        } 
else if (cmp > 0) {
            
// 右子树
            tree.reightChild = insert(t, tree.reightChild);

            
if ((height(tree.reightChild) - height(tree.leftChild)) == 2) {
                
// 当t比树右子树的元素还大的话,就是在树的右子树的右边插入节点,成为右子树的右子树,需要一次旋转
                if (compare(t, tree.reightChild.element) > 0) {
                    tree 
= rotateRightChild(tree);
                } 
else {
                    
// 当t比树右子树的元素还小的话,就是在树的右子树的左边插入节点,成为右子树的左子树,需要两次旋转
                    tree = doubleRotateRightChild(tree);
                }
            }

        } 
else {
            
// 树里面有这个树

        }
        tree.height 
= Math
                .max(height(tree.leftChild), height(tree.reightChild)) 
+ 1;
        
return tree;

    }

    
/**
     * 第1种情况需要进行顺时针旋转(右旋转)
     * 
     * 
@param k2
     * 
@return
     
*/
    
private AvlNode rotateLeftChild(AvlNode k2) {

        AvlNode k1 
= k2.leftChild;

        k2.leftChild 
= k1.reightChild;
        k1.reightChild 
= k2;

        k2.height 
= Math.max(height(k2.leftChild), height(k2.reightChild)) + 1;
        k1.height 
= Math.max(height(k1.leftChild), height(k2)) + 1;
        
return k1;

    }

    
/**
     * 
     * 第4种情况需要进行逆时针旋转(左旋转)
     * 
     * 
@param k2
     * 
@return
     
*/
    
private AvlNode rotateRightChild(AvlNode k2) {

        AvlNode k1 
= k2.reightChild;

        k2.reightChild 
= k1.leftChild;
        k1.leftChild 
= k2;

        k2.height 
= Math.max(height(k2.leftChild), height(k2.reightChild)) + 1;
        k1.height 
= Math.max(height(k1.reightChild), height(k2)) + 1;
        
return k1;

    }

    
/**
     * 第2种情况需要进行(右-左旋转)
     * 
     * 
@param k3
     * 
@return
     
*/
    
private AvlNode doubleRotateLeftChild(AvlNode k3) {
        AvlNode k1 
= k3.leftChild;
        k3.leftChild 
= rotateRightChild(k1);
        
return rotateLeftChild(k3);
    }

    
/**
     * 第3种情况需要进行(左-右旋转)
     * 
     * 
@param k3
     * 
@return
     
*/

    
private AvlNode doubleRotateRightChild(AvlNode k3) {
        AvlNode k1 
= k3.reightChild;
        k3.reightChild 
= rotateLeftChild(k1);
        
return rotateRightChild(k3);
    }

    
public int compare(int a, int b) {
        
return a - b;
    }

    
static class AvlNode {

        
private int element;
        
private int height;
        
private AvlNode leftChild;
        
private AvlNode reightChild;

        AvlNode(
int element) {
            
this(element, nullnull);
        }

        AvlNode(
int element, AvlNode left, AvlNode right) {
            
this.element = element;
            
this.leftChild = left;
            
this.reightChild = right;
        }

    }

    
public void sysout(AvlNode node) {
        
if (node != null) {

            AvlNode a 
= node.leftChild;
            sysout(a);
            
for (int i = 0; i < node.height; i++) {
                System.out.print(
"     ");
            }
            System.out.print(node.element);
            System.out.print(
"\n");
            AvlNode b 
= node.reightChild;
            sysout(b);
        }
    }

    
/**
     * 删除一个节点,找到平衡因子,他的左子树高度和右子树高度如果相差2的话,就需要旋转,而且旋转后,平衡因子的节点为根的树的高度肯定会
     * 
     * 下降1,这样平衡因子所在的树的高度下降1,也有可能需要进行旋转调整,这样调整一直到根节点
     * 
     * 
@param t
     * 
@param tree
     * 
@return
     
*/
    
public AvlNode delete(int t, AvlNode tree) {

        
if (tree == null)
            
return null;

        
int cmp = compare(t, tree.element);

        
if (cmp < 0) {
            tree.leftChild 
= delete(t, tree.leftChild);

            
if ((height(tree.reightChild) - height(tree.leftChild)) == 2) {
                
if (tree.leftChild == null) {
                    tree 
= rotateRightChild(tree);
                } 
else {
                    tree 
= doubleRotateRightChild(tree);

                }

            }
        } 
else if (cmp > 0) {
            tree.reightChild 
= delete(t, tree.reightChild);

            
if ((height(tree.leftChild) - height(tree.reightChild)) == 2) {
                
if (tree.reightChild == null) {
                    tree 
= rotateLeftChild(tree);
                } 
else {
                    tree 
= doubleRotateLeftChild(tree);
                }
            }
        } 
else if (cmp == 0) {
            tree 
= null;
        }

        
if (tree != null) {
            tree.height 
= Math.max(height(tree.leftChild),
                    height(tree.reightChild)) 
+ 1;
        }
        
return tree;

    }

    
public static void main(String[] args) {
        AvlTree avlTree 
= new AvlTree();
        AvlNode node 
= new AvlNode(20);
        
/*
         * Random random = new Random(); for (int i = 0; i < 10; i++) { int y =
         * random.nextInt(100) + 1; node = avlTree.insert(y, node); }
         
*/

        node 
= avlTree.insert(8, node);
        node 
= avlTree.insert(3, node);
        node 
= avlTree.insert(10, node);
        node 
= avlTree.insert(2, node);
        node 
= avlTree.insert(5, node);
        node 
= avlTree.insert(30, node);

        node 
= avlTree.insert(50, node);
        node 
= avlTree.insert(6, node);
        node 
= avlTree.insert(20, node);
        node 
= avlTree.insert(35, node);
        node 
= avlTree.insert(43, node);
        node 
= avlTree.insert(60, node);
        node 
= avlTree.insert(18, node);
        node 
= avlTree.insert(26, node);
        node 
= avlTree.insert(33, node);
        node 
= avlTree.insert(40, node);
        node 
= avlTree.insert(45, node);
        node 
= avlTree.insert(62, node);

        
// avlTree.sysout(node);

        node 
= avlTree.delete(2, node);
        avlTree.sysout(node);

    }
}

posted on 2011-08-29 17:38 nod0620 阅读(243) 评论(0)  编辑  收藏 所属分类: 数据结构


只有注册用户登录后才能发表评论。


网站导航:
 
<2011年8月>
31123456
78910111213
14151617181920
21222324252627
28293031123
45678910

导航

统计

常用链接

留言簿

随笔分类

随笔档案

文章分类

文章档案

搜索

最新评论

阅读排行榜

评论排行榜