博客
关于我
Tree--二叉树BinarySearchTree
阅读量:437 次
发布时间:2019-03-06

本文共 5694 字,大约阅读时间需要 18 分钟。

  BinarySearchTreeMap的实现

  

1 public interface Map
, 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 key25 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 order34 Iterable
keys(K lo, K hi);35 36 Iterable
keys();37 }
Map Interface

 


  二叉树的定义

  在计算机科学中,二叉树是每个节点最多有两个子树的树结构。通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)。二叉树常被用于实现二叉查找树和二叉堆。二叉树的左子节点 <  父节点 < 右子节点

  这是typical的二叉树的样子, null 代表子节点为空,从这张图可以看出,左子节点 9 小于 父节点 10 小于 右子节点 

  

1     private class Node
{2 private K k;3 private V v;4 private Node
left;5 private Node
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(节点)对象

        


   二叉树的插入操作

   假设我们依次插入 10 , 9, 15, 5 , 7 这5个元素到二叉树中。see what will happen 这是个动态图

1     @Override 2     public void put(K k, V v) { 3         root = put(root, k, v); //root 是根节点 4     } 5      6     private Node
put(Node
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 方法

  get方法简单来说就是要找到那个key相同的对象。比如我们要在「10 , 9, 15, 5 , 7 」上图所示中找到 7

  

  

1     @Override 2     public V get(K k) { 3         return get(root, k); 4     } 5      6     private V get(Node
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 { //equal14 return node.v;15 }16 17 }
get operation

  


  二叉树的删除操作

  其实想象一下,当你删除一个node的时候,你需要找一个替代node来代替这个node。

  这里又分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
delete(Node
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 node20 return node.left;21 else if (node.left == null) // if the left node is null then just replace this node with right node22 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 node25 }26 }27 }28 29 //删除从参数node开始的最小的node30 private Node
deleteMin(Node
node) {31 return delete(node, min(node));32 }33 34 private Node
deleteMax(Node
node) {35 return delete(node, max(node));36 }37 38 @Override39 public void deleteMin() {40 deleteMin(root);41 }42 43 @Override44 public void deleteMax() {45 deleteMax(root);46 }47 48 @Override49 public K min() {50 return min(root);51 }52 53 //get the smallest node in the given node54 private K min(Node
node) {55 if (node == null) return null;56 for (; node.left != null; node = node.left);57 return node.k;58 }59 60 @Override61 public K max() {62 return max(root);63 }64 //get the most max node in the given node65 private K max(Node
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

    有什么错误的地方欢迎大家指正哈

    

 

 

转载地址:http://gbcfz.baihongyu.com/

你可能感兴趣的文章
C++高精度模板
查看>>
错题重错之WYT的刷子 单调队列
查看>>
联赛模拟测试23 D. 真相 思维题
查看>>
牛顿迭代学习笔记
查看>>
Scala中的空
查看>>
设计模式学习笔记(二十三:解释器模式)
查看>>
Databricks 第4篇:pyspark.sql 分组统计和窗口
查看>>
SSISDB2:SSIS工程的操作实例
查看>>
业务工作流平台设计(七)
查看>>
业务工作流平台设计(八)
查看>>
大视角、大方向、大问题、大架构:(二)应用的相关问题
查看>>
SpringBoot Web(SpringMVC)
查看>>
javascript 之对象-13
查看>>
解决:angularjs radio默认选中失效问题
查看>>
java按照关键字指定的key删除redis(支持模糊删除)
查看>>
Jmeter-ForEach控制器
查看>>
windows环境下安装zookeeper(仅本地使用)
查看>>
Docker学习(十三)- docker rm 命令详解
查看>>
解决Eclipse左键无法查看maven第三方包的源代码,多图亲测可用【转】
查看>>
selnium远程机上传图片遇到的坑
查看>>