二叉搜索树是二叉树的一种扩展。树中的元素可以看作是有序的。由于特殊的结构,它非常适合进行二分查找操作,且查找的平均时间复杂度为O(logN)。不过其也可能退化为一个链表,此时查找的最坏时间复杂度变为O(N)。
特点
对于树中的任意节点X,它大于它的左子树中的所有节点值,且小于它的右子树中的所有节点值。(假设树中的元素都是互异的,不存在相等的元素值)
BinarySearchTree
本次实现中对于树中存储的元素并没有要求必须要实现Comparable
接口。而是同时结合了Comparator
和Comparable
接口。使用者可以在构造二叉搜索树时传入一个自定义的比较器,或者不使用比较器而是在存储的元素中实现Comparable
接口(此时Comparable
接口必须实现)。
成员变量
- private BinaryNode
root; //二叉搜索树的根节点 - private Comparator
cmp; //元素的自定义比较器
构造器
有两个构造器,其中一个是含参的构造器,可以传入一个自定义的比较器。在构造器中主要是初始化树根节点。
|
|
函数
|
|
内部比较方法,比较两个数的大小并返回结果。在方法中会判断是否有自定义比较器,有则用自定义比较器比较两个数大小,否则使用Comparable接口的comparaTo函数进行比较。
|
|
contains()
:查找树中是否包含某个元素,用递归的方法进行二分搜索。二分搜索法:用待查找的值x与当前结点比较,如果比节点值小,则在其左子树继续搜索;如果x比当前节点值大,则在其右子树中搜索。重复以上操作直到根节点位置,如果还没有搜索到匹配值则树中不包含x值。
|
|
insert()
:插入元素。每个元素都是作为树的新的叶子节点插入树中的。插入操作的平均时间复杂度为O(logN),但是如果是有序的元素进行插入操作的话则会是最坏情况,时间复杂度为O(logN),且会得到一棵退化的二叉搜索树(变成链表),这时候无论是删除还是查找操作时间复杂度就都变成了O(N)。
|
|
remove()
:删除元素x。二叉搜索树的删除操作还是相对比较简单的。待删除的节点主要为以下几种情况:
- 不存在该节点,删除失败;
- 待删除节点为叶子结点,则直接删除该节点;
- 待删除节点有一个孩子,只要删除该节点,将其孩子节点返回给其父节点即可;
- 待删除节点有两个孩子,这种情况下相对复杂一点点。通常的解决方法是用它的右子树中最小值替换节点值,然后删除右子树中的最小值即可(因为此时其右子树的最小值节点必没有左孩子,则变为2,3情况了)。但是这种删除元素的方法在若干次操作后可能会导致树失衡,即右子树高度普遍较低。所以我们可以采取随机删除右子树最小值或删除左子树最大值的方式。
|
|
findMin()
:查询最小值。树中最小值为左子树中最小元素。采用递归实现。
findMax()
:查询最大值。树中最大值为右子树中最大元素。采用非递归实现。
|
|
内部类
内部类实现二叉搜索树的节点。节点主要维护了数据和左、右孩子节点的引用。
|
|
源代码
|
|