Tree--二叉树BinarySearchTree
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的更多相关文章
- Leetcode 101 Symmetric Tree 二叉树
判断一棵树是否自对称 可以回忆我们做过的Leetcode 100 Same Tree 二叉树和Leetcode 226 Invert Binary Tree 二叉树 先可以将左子树进行Invert B ...
- Leetcode 110 Balanced Binary Tree 二叉树
判断一棵树是否是平衡树,即左右子树的深度相差不超过1. 我们可以回顾下depth函数其实是Leetcode 104 Maximum Depth of Binary Tree 二叉树 /** * Def ...
- [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 ...
- [LeetCode] 111. Minimum Depth of Binary Tree ☆(二叉树的最小深度)
[Leetcode] Maximum and Minimum Depth of Binary Tree 二叉树的最小最大深度 (最小有3种解法) 描述 解析 递归深度优先搜索 当求最大深度时,我们只要 ...
- UVA.548 Tree(二叉树 DFS)
UVA.548 Tree(二叉树 DFS) 题意分析 给出一棵树的中序遍历和后序遍历,从所有叶子节点中找到一个使得其到根节点的权值最小.若有多个,输出叶子节点本身权值小的那个节点. 先递归建树,然后D ...
- [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 ...
- [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 ...
- [LeetCode] Serialize and Deserialize Binary Tree 二叉树的序列化和去序列化
Serialization is the process of converting a data structure or object into a sequence of bits so tha ...
- [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 ...
- [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 ...
随机推荐
- AtCoder Beginner Contest 181 题解
总结 第一次 \(AK\ ABC\) 的比赛,发一个截图纪念一下 A - Heavy Rotation 题目大意 一个人一开始穿白衣服,一天后换成黑衣服,再过一天又换成白衣服,问第 \(n(n \le ...
- Serilog源码解析——使用方法
在上两篇文章(链接1和链接2)中,我们通过一个简易 demo 了解到了一个简单的日志记录类库所需要的功能,即一条日志有哪些数据,以及如何通过一次记录的方式将同一条日志消息记录到多个日志媒介中.在本文中 ...
- Ideas and Tricks
1.树上拓扑排序计数 结论$\dfrac{n!}{\prod\limits_{i=1}^n size_i}$ 对于节点$i$,其子树随意排序的结果是$size[i]!$ 但$i$需要排在第一位,只有$ ...
- Python如何快速复制序列?
1 基本用法 把序列乘以一个整数,就会产生一个新序列.这个新序列是原始序列复制了整数份,然后再拼接起来的结果. l=[1,2,3] l2=l * 3 logging.info('l2 -> %s ...
- Facebook 的神仙组长什么样?
这里是<齐姐聊大厂>系列的第 14 篇 每周五早上 8 点,与你唠唠大厂的那些事 号外号外!前 12 篇已出 PDF:公粽号后台回复「大厂」即可获得! ❝ 小齐说: 这篇文章是来自阿米粥的 ...
- 微软面试题: LeetCode 91. 解码方法 出现次数:3
题目描述: 一条包含字母 A-Z 的消息通过以下方式进行了编码: 'A' -> 1'B' -> 2...'Z' -> 26给定一个只包含数字的非空字符串,请计算解码方法的总数. 示例 ...
- Spring源码之Bean生命周期
https://www.jianshu.com/p/1dec08d290c1 https://www.cnblogs.com/zrtqsk/p/3735273.html 总结 将class文件加载成B ...
- 面经手册 · 第18篇《AQS 共享锁,Semaphore、CountDownLatch,听说数据库连接池可以用到!》
作者:小傅哥 博客:https://bugstack.cn Github:https://github.com/fuzhengwei/CodeGuide/wiki 沉淀.分享.成长,让自己和他人都能有 ...
- 11.java设计模式之享元模式
基本需求: 小型的外包项目,给客户A做一个产品展示网站,客户A的朋友感觉效果不错,也希望做这样的产品展示网站,但是要求都有些不同 每个客户要求发布的方式不一样,A要求以新闻的方式发布,B要求以博客的方 ...
- Python_异常处理、调试
1.try except 机制 # 错误处理 # 一般程序都要用到错误捕获,当没有加且有错误的时候Python解释器会执行错误捕获,且是一层层向上捕获[所以问题点会在最下面] try: print(' ...