BinarySearchTreeMap的实现

  

 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


  二叉树的定义

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

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

  

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(节点)对象

        


   二叉树的插入操作

   假设我们依次插入 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<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 方法

  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<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

  


  二叉树的删除操作

  其实想象一下,当你删除一个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<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

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

    

Tree--二叉树BinarySearchTree的更多相关文章

  1. Leetcode 101 Symmetric Tree 二叉树

    判断一棵树是否自对称 可以回忆我们做过的Leetcode 100 Same Tree 二叉树和Leetcode 226 Invert Binary Tree 二叉树 先可以将左子树进行Invert B ...

  2. Leetcode 110 Balanced Binary Tree 二叉树

    判断一棵树是否是平衡树,即左右子树的深度相差不超过1. 我们可以回顾下depth函数其实是Leetcode 104 Maximum Depth of Binary Tree 二叉树 /** * Def ...

  3. [CareerCup] 4.7 Lowest Common Ancestor of a Binary Search Tree 二叉树的最小共同父节点

    4.7 Design an algorithm and write code to find the first common ancestor of two nodes in a binary tr ...

  4. [LeetCode] 111. Minimum Depth of Binary Tree ☆(二叉树的最小深度)

    [Leetcode] Maximum and Minimum Depth of Binary Tree 二叉树的最小最大深度 (最小有3种解法) 描述 解析 递归深度优先搜索 当求最大深度时,我们只要 ...

  5. UVA.548 Tree(二叉树 DFS)

    UVA.548 Tree(二叉树 DFS) 题意分析 给出一棵树的中序遍历和后序遍历,从所有叶子节点中找到一个使得其到根节点的权值最小.若有多个,输出叶子节点本身权值小的那个节点. 先递归建树,然后D ...

  6. [LeetCode] 111. Minimum Depth of Binary Tree 二叉树的最小深度

    Given a binary tree, find its minimum depth. The minimum depth is the number of nodes along the shor ...

  7. [LeetCode] 543. Diameter of Binary Tree 二叉树的直径

    Given a binary tree, you need to compute the length of the diameter of the tree. The diameter of a b ...

  8. [LeetCode] Serialize and Deserialize Binary Tree 二叉树的序列化和去序列化

    Serialization is the process of converting a data structure or object into a sequence of bits so tha ...

  9. [LeetCode] Lowest Common Ancestor of a Binary Tree 二叉树的最小共同父节点

    Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree. According ...

  10. [LeetCode] Minimum Depth of Binary Tree 二叉树的最小深度

    Given a binary tree, find its minimum depth. The minimum depth is the number of nodes along the shor ...

随机推荐

  1. 《Google软件测试之道》 第一章google软件测试介绍

    前段时间比较迷茫,没有明确的学习方向和内容.不过有一点应该是可以肯定的:迷茫的时候就把空闲的时间用来看书吧! 这本书,目前只是比较粗略的看了一遍,感触很大.以下是个人所作的笔记,与原文会有出入的地方. ...

  2. Flink系列(0)——准备篇(流处理基础)

    Apache Flink is a framework and distributed processing engine for stateful computations over unbound ...

  3. linux-挂载NFS网络文件系统教程

    目录 前言 链接 参考 笔录草稿 NFS环境搭建 前言 本文实现需要联网 链接 野火NFS介绍 NFS详细介绍 NFS简要介绍 参考 上面链接 笔录草稿 NFS环境搭建 一些目标配置 服务主机共享目录 ...

  4. Ubuntu17.10 React Native 环境搭建

    React Native 环境搭建 环境:ubuntu17.10 安装依赖 必须安装的依赖有:Node.React Native 命令行工具以及 JDK 和 Andriod Studio. 安装nod ...

  5. 4、Django之视图层

    一 视图函数 视图函数,简称视图,属于Django的视图层,默认定义在views.py文件中,是用来处理web请求信息以及返回响应信息的函数,所以研究视图函数只需熟练掌握两个对象即可:请求对象(Htt ...

  6. kubernetes-1.18.2集群安装-02

    一.基础配置 修改主机名 # 在 172.17.32.23 上:hostnamectl set-hostname k8s-master01bash​# 在 172.17.32.38 上:hostnam ...

  7. vite 搭建Vue3.0项目

    1.全局安装vite:npm install create-vite-app -g 2.创建项目:npx create-vite-app project-name 3.cd project-name ...

  8. MySQL视图详细介绍

    前言: 在MySQL中,视图可能是我们最常用的数据库对象之一了.那么你知道视图和表的区别吗?你知道创建及使用视图要注意哪些点吗?可能很多人对视图只是一知半解,想详细了解视图的同学看过来哟,本篇文章会详 ...

  9. 用seaborn绘制散点图

    散点图可以显示观察数据的分布,描述数据的相关性,matlibplot也可以绘制散点图,不过我一般优先使用seaborn库的sctterplot()绘制,下面就介绍一下如何用seaborn.scatte ...

  10. day92:flask:flask简介&基本运行&路由&HTTP请求和响应

    目录 1.Flask简介 2.关于使用flask之前的准备 3.flask的基本运行 4.flask加载配置 5.传递路由参数(没有限定类型) 6.传递路由参数(通过路由转换器限定路由参数的类型) 7 ...