赞
踩
(一)二叉搜索树(Binary Search Tree)的需求分析
(二)二叉搜索树(Binary Search Tree)的概念
(三)二叉搜索树(Binary Search Tree)的设计
(四)二叉搜索树(Binary Search Tree)之add:根节点
(五)二叉搜索树(Binary Search Tree)之add:思路
(六)二叉搜索树(Binary Search Tree)之add:实现
(七)二叉搜索树(Binary Search Tree)之compare:comparable
(八)二叉搜索树(Binary Search Tree)之compare:comparator
(九)二叉搜索树(Binary Search Tree)之compare:完美结合
(十)二叉搜索树(Binary Search Tree)之compare:匿名类
(十一)二叉搜索树(Binary Search Tree)之打印器:基本使用
(十二)二叉搜索树(Binary Search Tree)之打印器:Person类
(十三)二叉搜索树(Binary Search Tree)之打印器:更多用法
(十四)二叉搜索树(Binary Search Tree)之打印器:文件
(十五)二叉搜索树(Binary Search Tree):网站推荐
(十六)二叉搜索树(Binary Search Tree):值相等的处理
说明:
说明:
说明:对于之前的数组和链表都有索引(int index)的概念,但是二叉搜索树没有索引
原因:二叉树是树形结构,非线性结构没办法标索引
代码大致框架如下:
首先写一个Node内部类,如下:
private static class Node<E> {
E element;
Node<E> left;
Node<E> right;
Node<E> parent;
public Node(E element, Node<E> parent) {
this.element = element;
this.parent = parent;
}
}
构造节点的时候传递的element通常是不允许为null的,写一个检查的方法,如下:
private void elementNotNullCheck(E element) {
if (element == null) {
throw new IllegalArgumentException("element must not be null");
}
}
第一次添加节点,添加的是根节点,如下:
public void add(E element) {
elementNotNullCheck(element);
//添加第一个节点
if (root == null) {
root = new Node<>(element, null);
size++;
return;
}
//添加的不是第一个节点
}
对下面这颗二叉树添加12和1,如下:
添加之后,结果如下:
过程:以添加12为例,首先用12跟7比较,发现12比7大,就继续找7的右节点
以此类推,找到最后发现还是比11大,就把12放在11的右节点
步骤:
parent.left = node
或者parent.right = node
遇到值相等的元素该如何处理?建议覆盖旧的值
先写一个compare(E e1, E e2)
方法实现比较功能,但是先留空,如下:
/**
* 返回值等于0,代表e1等于e2
* 返回值大于0,代表e1大于e2
* 返回值小于0,代表e1小于e2
*
* @param e1
* @param e2
* @return
*/
private int compare(E e1, E e2) {
return 0;
}
add(E element)
方法如下:
public void add(E element) { elementNotNullCheck(element); //添加第一个节点 if (root == null) { root = new Node<>(element, null); size++; return; } //添加的不是第一个节点 Node<E> node = root;//找到父节点 Node<E> parent = null;//用于保存父节点 int cmp = 0;//用于记录方向(左还是右) while (node != null) {//只有node不为空,才拿node的值跟element做比较 cmp = compare(element, node.element);//记录方向 parent = node;//保存父节点,否则while循环结束,node为null,无法进行下一步操作 if (cmp > 0) { node = node.right;//拿node的右节点继续做比较 } else if (cmp < 0) { node = node.left;//拿node的左节点继续做比较 } else {//相等 return;//最好是替换,这里先直接返回 } } //看插入到父节点的哪个位置 Node<E> newNode = new Node<>(element, parent);//创建一个新节点 if (cmp > 0) { parent.right = newNode; } else { parent.left = newNode; } size++; }
首先编写一个Comparable接口,如下:
我们让BinarySearchTree里面的泛型E继承Comparable接口
BinarySearchTree里的元素必须实现Comparable接口,并重写int compareTo(E e)
方法,如下:
在Person类中重写int compareTo(E e)
方法,并且在BinarySearchTree中调用,如下:
二叉搜索树要求小的节点放在左子树,大的节点放在右子树,两种情况如下:
而刚才继承comparable接口的写法就会存在弊端,如下:
如果我再创建一颗树(bst3),那么这两棵树只能都是:年龄小的节点小或年龄小的节点大
如果我想bst2属于年龄小的节点小,而bst3属于年龄小的节点大就需要用下面这种方法了
首先编写一个Comparator接口,如下:
通过构造函数的方法传递比较器接口,如下:
这样就可以实现个性化比较器了,如下:
在BinarySearchTree把上一个比较器相关的代码注释掉,如下:
最后修改compare(E e1, E e2)
方法,如下:
我们理想的状态是:
我们接下来将这两者进行完美结合
再写一个空参的构造方法,如下:
修改compare(E e1, E e2)
方法,如下:
其实刚才写的Comparable接口和Comparator接口都可以删掉,JDK官方给我们提供了一样的接口
除了像刚才那样让一个类去实现接口以外(如下),JDK官方还提供匿名类的写法
写法如下:
注意:
我们要怎么样才能看到二叉树打印的结果呢?
打开 http://520it.com/binarytrees/ 选中二叉搜索树,然后 输入相关节点的值,如下:
上面的是预期效果,实际代码写得对不对要在代码中验证
首先把资料包中的printer文件夹拷贝过来,如下:
让二叉搜索树实现BinaryTreeInfo接口,如下:
并且重写4个方法,如下:
最后调用静态方法打印即可,如下:
传递不同的参数,会打印出不同的效果,如下:
重写Person类的toString()
方法,如下:
效果如下:
可以把parent也打印出来,方便后期调试,如下:
使用匿名类的写法,可以打印任意东西,不局限于打印二叉树
首先把资料包里面的file文件夹拷贝过来,如下:
最后调用即可,如下:
注意:重载方法的第三个参数,是指是否追加到文件末尾
http://520it.com/binarytrees/
http://btv.melezinek.cz/binary-search-tree.html
https://www.cs.usfca.edu/~galles/visualization/Algorithms.html
这样做的好处是对于自定义对象而言的,比如说之前的Person类用于比较的是age,两个age相等的Person对象在二叉树看来是等价的,但是他们的其它字段可能不一样,所以最好还是用新的覆盖旧的
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。