二叉查找树(BST)(自己动手写API系列三)*
这次的教学可能会比较长一点 所以也希望大家可以耐心看
下面的代码里面会贴一些讲解 觉得烦也没事 最下面我会把全部的代码贴出来 你可以拿纯净的
然后这次的语言我还是 选择用java 如果不会Java的 不着急要代码 你也可以耐心看学习 用你学过的语言去实现以下
毕竟语言只是工具
好了 先看一下类名
public class BinarySearchTree <Key extends Comparable</Key>, Value>
类名 : BinarySearchTree
参数 : Key 要求 继承了 Comparable 还有 一个Value 说白了 就是键值对
然后先简单的了解一下 二叉树
二叉树
什么是二叉树? 看图
你会发现这是什么啊? 别着急
这会应该会比较像了吧
我们这里 data是数据域 你可以存一大堆乱七八糟的
二叉树 :
二叉树其实就是一颗长的像树的东西 它是每个结点有两个分支 左分支 和 右分支 也可以叫左儿子和右儿子
而他本身的这个结点叫做父结点
二叉树我们可以规定一个约定
比如 : 每个结点的 左儿子 < 父结点 <右儿子 也就是左边的最小 自己在中间 右儿子最大
基本的二叉树就介绍到这里
让我们看一下这次教学的方法(函数)
getSize() 方法 返回这颗树有多少结点
get(Key key) 方法 通过键拿值 返回 Value
put(Key key, Value val) 方法 存储一个结点 存储他们的键值对
getMin() 方法 获得最小的那个值 返回一个 Value
getMax() 方法 获得最大的那个值 返回一个 Value
floor(Key key) 方法 向下取整 返回一个Key 返回比你传入key 最接近并且小于等于的键
ceiling(Key key) 方法 向上取整 返回一个Key 返回比你传入key 最接近并且大于等于的键
select(int k) 方法 返回一个 Key 返回排名第k个键
rank(Key key) 方法 返回一个int值 返回这个键排名多少
deleteMin() 方法 删除最小的那个结点
deleteMax() 方法 删除最大的那个结点
delete(Key key) 方法 删除一个值 返回一个Value 返回你要删除的那个键对应的值
方法就这么多 其实要想加还有 让我们一个 一个看
因为是二叉树,所以我们用到了结点 结点是一个内部类
内部类其实可以很好的隐藏自己 可以用到外部类 又可以很好的隐藏自己看一下内部类的定义
private class Node { //内部类 用private 修饰不暴露内部细节
private Key key; // 内部类的键
private Value val; //内部类的值
private Node left; //结点左儿子
private Node right; // 结点右儿子
private int N; //子树的个数
public Node(Key key, Value val, int N) {
this.key = key; this.val = val; this.N = N;
}
}
然后看一下成员 其实成员就只有一个 : private Node root; 就是树根
接下来讲方法 因为根据开闭原则 我不希望暴露内部的细节 因为有内部类而我每个方法基本都要用到树根
所以每个方法都应该有一个private方法 和 public 方法 这里听不懂没事 往下慢慢看
1. int getSize() 方法
这个比较简单, 因为内部类中有个N也就是个数 所以 返回树根的个数就好
所以 这个就直接贴了
public int getSize() {
return getSize(root);
}
private int getSize(Node x) {
if(x == null) return 0;
else return x.N;
}
共有的方法提供给外部 但是 私有的方法才是真正起主导作用的
这样的重载方法就可以很好的起到封闭原则 没理解继续往下
2. get(Key key) 方法
记得一开始我们的那个约定 左儿子最小 右儿子最大 类似于下图
这是百度找的图 懒得自己画
其实你会发现 如果把8当成父结点 左边的都比8小 而 右边的都比8大
重!!: 每一个结点其实都可以当成一个子树
把3当成父结点 也满足那个约束
所以你发现查找起来就会非常方便
你只要判断一下 当前的这个结点比你要查找的大还是小
你要查找的比当前的大 那么肯定你要查找的在右边
同理 如果小了 肯定在左边 如果刚刚好 命中返回
比如你要查找6
发现6 比 8 小 你是不是只用看左边就OK
然后树直接变成了这样 直接淘汰了一半接下来 比较6 和3
6比