Tree--二叉樹BinarySearchTree

  BinarySearchTreeMap的實現java

  

 1 public interface Map<K extends Comparable<K>, V> {
 2     void put(K k, V v);
 3     
 4     V get(K k);
 5     
 6     void delete(K k);
 7     
 8     boolean contains(K k);
 9     
10     boolean isEmpty();
11     
12     int size();
13     
14     int size(K lo, K hi);
15     
16     K min();
17     
18     K max();
19     
20     K floor(K k);
21     
22     K ceiling(K k);
23     
24     // the number of keys less than key
25     int rank(K k);
26     
27     K select(int k);
28     
29     void deleteMin();
30     
31     void deleteMax();
32     
33     // keys in [lo , hi] in sorted order
34     Iterable<K> keys(K lo, K hi);
35     
36     Iterable<K> keys();
37 }
Map Interface

 


  二叉樹的定義node

  在計算機科學中,二叉樹是每一個節點最多有兩個子樹的樹結構。一般子樹被稱做「左子樹」(left subtree)和「右子樹」(right subtree)。二叉樹常被用於實現二叉查找樹和二叉堆。二叉樹的左子節點 <  父節點 < 右子節點git

  這是typical的二叉樹的樣子, null 表明子節點爲空,從這張圖能夠看出,左子節點 9 小於 父節點 10 小於 右子節點 github

  

1     private class Node<K, V> {
2         private K k;
3         private V v;
4         private Node<K, V> left;
5         private Node<K, V> right;
6         private int size;
7         Node(K k, V v) { this.k = k; this.v = v; }
8         Node(K k, V v, int size) { this.k = k; this.v = v; this.size = size;}
9     }
Node(節點)對象

        


   二叉樹的插入操做app

   假設咱們依次插入 10 , 9, 15, 5 , 7 這5個元素到二叉樹中。see what will happen 這是個動態圖less

 1     @Override
 2     public void put(K k, V v) {
 3         root = put(root, k, v); //root 是根節點
 4     }
 5     
 6     private Node<K, V> put(Node<K, V> node, K k, V v) {
 7         if (node == null) return new Node<>(k, v, 1);
 8         int cmp = node.k.compareTo(k);
 9         if (cmp > 0) { //node的k大一點 放到左邊的數中
10             node.left = put(node.left, k, v);
11         } else if (cmp < 0) { //node的k小一點 放到右邊的數中
12             node.right = put(node.right, k, v);
13         } else node.v = v;
14         
15         node.size = size(node.left) + size(node.right) + 1;
16         return node;
17     }
put operation (插入)

 

 

  二叉樹的get 方法ide

  get方法簡單來講就是要找到那個key相同的對象。好比咱們要在「10 , 9, 15, 5 , 7 」上圖所示中找到 7this

  

  

 1  @Override  2     public V get(K k) {  3         return get(root, k);  4  }  5     
 6     private V get(Node<K, V> node, K k) {  7         
 8         if (node == null) return null; //not find
 9         else if (node.k.compareTo(k) > 0) { //node的k大一點 放到左邊的數中
10             return get(node.left, k); 11         } else if (node.k.compareTo(k) < 0) { //node的k小一點 放到右邊的數中
12             return get(node.right, k); 13         } else {                      //equal
14             return node.v; 15  } 16         
17     }
get operation

  


  二叉樹的刪除操做spa

  其實想象一下,當你刪除一個node的時候,你須要找一個替代node來代替這個node。3d

  這裏又分3種狀況。首先假設你有以下的樹結構

  

  1.第一種狀況是這個刪除的節點的左右節點都是null。

    好比我要刪除3節點。其實只要直接把3節點reset 爲null 就能夠了。變成以下

  

   2.第二種狀況是刪除的節點的2個子節點中有一個子節點爲null

     好比我要刪除15。 15 的左節點是12 右節點是 null,因此符合這個狀況

       這個時候只須要直接把須要刪除的節點 reset 爲 非空的子節點就能夠了

                 因此在這裏只須要把15的值替代爲12

  

  3.第三種狀況是刪除的節點的2個子節點都不爲null,

    這個時候其實能夠有2個選擇,一個是把刪除的節點替換爲右子節點爲根節點的那個樹中最小的節點

    好比我要刪除10, 右節點爲15(二叉樹的刪除操做的那個圖,不是上面的那個圖),15這個節點爲根節點的樹中總共有2個元素(15和12),12是最小的。因此把須要刪除的節點替換爲12。刪除後以下

  

    另一種選擇是把左節點爲根節點的樹中最大的值取出來,把須要刪除的那個節點替換爲這個左節點最大的元素(2個選擇沒什麼區別)

    

 1     @Override
 2     public void delete(K k) {
 3         delete(root, k);
 4     }
 5     //delete the k in the node tree and reset the size prorperty of this tree and subtrees to correct value 
 6     private Node<K, V> delete(Node<K, V> node, K k) {
 7         if (node == null) return null;  //沒有找到這個node
 8         
 9         int cmp = node.k.compareTo(k);
10         if (cmp > 0) {
11             node.left = delete(node.left, k);
12             node.size = size(node.left) + size(node.right) + 1;
13             return node;
14         } else if (cmp < 0) {
15             node.right = delete(node.right, k);
16             node.size = size(node.left) + size(node.right) + 1;
17             return node;
18         } else {    //hit the key 
19             if (node.right == null) //if the right node is null then just replace this node with left node
20                 return node.left;
21             else if (node.left == null) // if the left node is null then just replace this node with right node
22                 return node.right;
23             else {
24                 return deleteMin(node.right); // if both the subnodes are not null replace this node with the smallest node in the right sub node
25             }
26         }
27     }
28     
29     //刪除從參數node開始的最小的node
30     private Node<K, V> deleteMin(Node<K, V> node) {
31         return delete(node, min(node));
32     }
33     
34     private Node<K, V> deleteMax(Node<K, V> node) {
35         return delete(node, max(node));
36     }
37     
38     @Override
39     public void deleteMin() {
40         deleteMin(root);
41     }
42     
43     @Override
44     public void deleteMax() {
45         deleteMax(root);
46     }
47     
48     @Override
49     public K min() {
50         return min(root);
51     }
52     
53     //get the smallest node in the given node
54     private K min(Node<K, V> node) {
55         if (node == null) return null;
56         for (; node.left != null; node = node.left);
57         return node.k;
58     }
59     
60     @Override
61     public K max() {
62         return max(root);
63     }
64     //get the most max node in the given node
65     private K max(Node<K, V> node) {
66         if (node == null) return null;
67         for (node = root; node.right != null; node = node.right);
68         return node.k;
69     }
delete operation 刪除操做

 

 

 


   分析

    BinarySearchTree 有一個最大的缺點,就是若是插入的元素是ordered,好比我插入 1 2 3 4 5  6 這樣子,元素都會排在一邊。這樣子查找起來路徑很長,效率很低。

    若是插入的元素是隨機的,那麼全部的get put 操做的時間複雜度應該是 和 log2(N) 成正比的

    具體的實現能夠參考這個。https://github.com/Cheemion/algorithms/blob/master/src/com/algorithms/tree/BinarySearchTreeMap.java

    有什麼錯誤的地方歡迎你們指正哈

相關文章
相關標籤/搜索