AVLTree

这个很好玩啊,有个博客讲得非常好:

http://www.cnblogs.com/skywang12345/p/3577479.html

基本上要点都在里面。

 

我觉得最核心的一点就是对树的四种操作。

(图中k的交标代表了在图中的大小顺序,1最小。比如图中有三个节点k1,k2,k3,关系就是k1<k2<k3)

1. LL:新插入一个节点后,某一个节点的左子树的左子树深度过大,造成了不平衡

       k2                  k1
      /  \                /  \
     k1   C    ===>      A   k2
    /  \                     / \
   A    B                   B   C  

操作的方式是,把k1设置成根节点,所以k2就要变成k1的右子树,但是k1本来可能也有右子树,这个右子树就要过继给k2当它的左子树。

造型变换以后,需要更新各个节点的height,从下往上更新,先更新k2的,再更新k1的,然后返回k1(因为它是现在的根节点)

代码如下:

1     private Node LL(Node k2) {
2         Node k1 = k2.left;
3         k2.left = k1.right;
4         k1.right = k2;
5         k2.height = Math.max(height(k2.left), height(k2.right)) + 1;
6         k1.height = Math.max(height(k1.left), height(k2)) + 1;
7         return k2;
8     }

 

2. RR: 新插入一个节点以后,某一个节点的右子树的右子树深度过大,造成了不平衡

       k1                  k2
      /  \                /  \
     A   k2    ===>      k1   C
        /  \            / \
       B    C          A   B  

操作的方式是,把k2设置成根节点,所以k1就要变成k2的左子树,但是k2本来可能也有左子树,所以k2的右子树就要过继给k1当它的右子树。

造型变换以后,需要更新各个节点的height,从下往上更新,先更新k1的,再更新k2的,然后返回k2

代码如下:

1     private Node RR (Node k1){
2         Node k2 = k1.right;
3         k1.right = k2.left;
4         k2.left = k1;
5         k1.height = Math.max(height(k1.left), height(k1.right)) + 1;
6         k2.height = Math.max(height(k1), height(k2)) + 1;
7         return k2;
8     }

 

2. LR: 新插入一个节点以后,某一个节点的左子树的右子树深度过大,造成了不平衡

       k3                  k3                 k2
      /  \                /  \               /  \
     k1   D    ===>      k2   D    ===>     k1   k3     
    /  \                /  \               /  \ /  \
   A    k2             k1   C             A   B C   D
       /  \           /  \
      B    C         A    B  

操作的方式是,我们先忽略k3这个节点,只看k1,k2构成的树,这是一棵失衡的RR树,所以先对k1k2进行RR操作,然后捋顺了之后出现中间图的情况:一棵LL树,再对k3进行LL操作

因为RR和LL操作里面自带了height的调整,所以这里就不需要单独操作了

代码如下:

1     private Node LR(Node k3) {
2         k3.left = RR(k3.left);
3         return LL(k3);
4     }

 

4. RL : 新插入一个节点以后,某一个节点的右子树的左子树深度过大,造成了不平衡

       k1                  k1                 k2
      /  \                /  \               /  \
     A   k3    ===>      A   k2    ===>     k1   k3     
        /  \                /  \           /  \ /  \
       k2   D              B   k3         A   B C   D
      /  \                    /  \
     B    C                  C    D  

操作的方式是,我们先忽略k1这个节点,只看k2,k3构成的树,这是一棵失衡的LL树,所以先对k2k3进行LL操作,然后捋顺了之后出现中间图的情况:一棵RR树,再对k1进行RR操作

因为RR和LL操作里面自带了height的调整,所以这里就不需要单独操作了

代码如下:

1     private Node RL(Node k1) {
2         k1.right = LL(k1.right);
3         return RR(k1);
4     }

 

有了这四种基础的操作,insert就比较好完成了

思路如下:

 1 如果root == null
 2 
 3   创建root点
 4 
 5 如果key > root.key(也就是说,需要插入的节点在根节点的右侧)
 6 
 7   root.right = insert(key, root.right);
 8 
 9   因为右侧新加了节点,所以有可能失衡,如果右侧的左右高度差变成了2,就需要调整:
10 
11     如果key比root.right的值要大,也就是一棵失衡的RR树:
12 
13       RR(root)
14 
15     否则,就是右子树的左子树出了问题,
16 
17       RL(root)
18 
19 否则(也就是需要插入的节点在根节点的左子树上)
20 
21    root.left = insert(key, root.left)
22 
23    因为左侧新加了节点,所以有可能失衡,如果左侧的左右高度差变成了2,就需要调整:
24 
25      如果key比root.right的值要大,也就是一棵失衡的LR树:
26 
27        LR(root)
28 
29      否则,就是左子树的左子树出了问题,
30 
31        LL(root)
32 
33 返回root

代码如下:

 1 public void insert(int key, int value) {
 2         root = insert(key, value, root);
 3     }
 4 
 5 
 6     private Node insert(int key, int value, Node root) {
 7         if(root == null) {
 8             root = new Node(key, value);
 9         } else if(root.key == key){
10             root.value = value;
11         } else if(root.key > key) {
12             root.left = insert(key, value, root.left);
13             if(height(root.left) - height(root.right) == 2) {
14                 if(root.key > key) {
15                     root = LL(root);
16                 } else {
17                     root = LR(root);
18                 }
19             }
20         } else {
21             root.right = insert(key, value, root.right);
22             if(height(root.right) - height(root.left) == 2) {
23                 if(root.key > key) {
24                     root = RL(root);
25                 } else{
26                     root = RR(root);
27                 }
28             }
29         }
30         root.height = Math.max(height(root.left), height(root.right)) + 1;
31         return root;
32     }

就是这样了~

Node本身的结构

 1     class Node {
 2         int key;
 3         int value;
 4         int height;
 5         Node left;
 6         Node right;
 7         public Node(int key, int value) {
 8             this.key = key;
 9             this.value = value;
10             this.height = 0;
11         }
12     }

 

两个辅助函数

public void print() {
        if(root == null) {
            return;
        }
        int curLevel = 1;
        int nextLevel = 0;
        Queue<Node> queue = new LinkedList<>();
        queue.offer(root);
        while(!queue.isEmpty()) {
            Node cur = queue.poll();
            System.out.println((cur.key + ": " + cur.value) + " ");
            curLevel--;
            if(cur.left != null) {
                queue.offer(cur.left);
                nextLevel++;
            }
            if(cur.right != null) {
                queue.offer(cur.right);
                nextLevel++;
            }
            if(curLevel == 0) {
                System.out.println();
                curLevel = nextLevel;
                nextLevel = 0;
            }
        }
    }



    public int height(Node root) {
        if(root == null) {
            return 0;
        }
        return root.height;
    }

//随手search功能
    public int search(int key) {
        Node res = searchHelper(key, root);
        return res == null? -1: res.value;

    }

    private Node searchHelper(int key, Node root) {
        if(root == null) {
            return null;
        } else if(root.key == key) {
            return root;
        } else if(root.key < key) {
            return searchHelper(key, root.right);
        } else {
            return searchHelper(key, root.right);
        }
    }

删除会死,我就不写了

  1 public class AVLTree {
  2     class Node {
  3         int key;
  4         int value;
  5         int height;
  6         Node left;
  7         Node right;
  8         public Node(int key, int value) {
  9             this.key = key;
 10             this.value = value;
 11             this.height = 0;
 12         }
 13     }
 14 
 15     Node root;
 16 
 17     public int height(Node root) {
 18         if(root == null) {
 19             return 0;
 20         }
 21         return root.height;
 22     }
 23 
 24     private Node LL(Node k2) {
 25         Node k1 = k2.left;
 26         k2.left = k1.right;
 27         k1.right = k2;
 28         k2.height = Math.max(height(k2.left), height(k2.right)) + 1;
 29         k1.height = Math.max(height(k1.left), height(k2)) + 1;
 30         return k2;
 31     }
 32 
 33     private Node RR (Node k1){
 34         Node k2 = k1.right;
 35         k1.right = k2.left;
 36         k2.left = k1;
 37         k1.height = Math.max(height(k1.left), height(k1.right)) + 1;
 38         k2.height = Math.max(height(k1), height(k2)) + 1;
 39         return k2;
 40     }
 41 
 42     private Node LR(Node k3) {
 43         k3.left = RR(k3.left);
 44         return LL(k3);
 45     }
 46 
 47     private Node RL(Node k1) {
 48         k1.right = LL(k1.right);
 49         return RR(k1);
 50     }
 51 
 52     public void insert(int key, int value) {
 53         root = insert(key, value, root);
 54     }
 55 
 56 
 57     private Node insert(int key, int value, Node root) {
 58         if(root == null) {
 59             root = new Node(key, value);
 60         } else if(root.key == key){
 61             root.value = value;
 62         } else if(root.key > key) {
 63             root.left = insert(key, value, root.left);
 64             if(height(root.left) - height(root.right) == 2) {
 65                 if(root.key > key) {
 66                     root = LL(root);
 67                 } else {
 68                     root = LR(root);
 69                 }
 70             }
 71         } else {
 72             root.right = insert(key, value, root.right);
 73             if(height(root.right) - height(root.left) == 2) {
 74                 if(root.key > key) {
 75                     root = RL(root);
 76                 } else{
 77                     root = RR(root);
 78                 }
 79             }
 80         }
 81         root.height = Math.max(height(root.left), height(root.right)) + 1;
 82         return root;
 83     }
 84 
 85     public int search(int key) {
 86         Node res = searchHelper(key, root);
 87         return res == null? -1: res.value;
 88 
 89     }
 90 
 91     private Node searchHelper(int key, Node root) {
 92         if(root == null) {
 93             return null;
 94         } else if(root.key == key) {
 95             return root;
 96         } else if(root.key < key) {
 97             return searchHelper(key, root.right);
 98         } else {
 99             return searchHelper(key, root.right);
100         }
101     }
102 
103     public void print() {
104         if(root == null) {
105             return;
106         }
107         int curLevel = 1;
108         int nextLevel = 0;
109         Queue<Node> queue = new LinkedList<>();
110         queue.offer(root);
111         while(!queue.isEmpty()) {
112             Node cur = queue.poll();
113             System.out.println((cur.key + ": " + cur.value) + " ");
114             curLevel--;
115             if(cur.left != null) {
116                 queue.offer(cur.left);
117                 nextLevel++;
118             }
119             if(cur.right != null) {
120                 queue.offer(cur.right);
121                 nextLevel++;
122             }
123             if(curLevel == 0) {
124                 System.out.println();
125                 curLevel = nextLevel;
126                 nextLevel = 0;
127             }
128         }
129     }
130 
131     public static void main(String[] args) {
132         AVLTree map = new AVLTree();
133         map.insert(1, 2);
134         map.print();
135         map.insert(2, 3);
136         map.print();
137         map.insert(3, 4);
138         map.print();
139     }
140 }
View Code

 

posted @ 2016-10-31 07:43  warmland  阅读(158)  评论(0编辑  收藏  举报