在链表实现的二叉搜索树中,对于每一个Node需满足:左子Node < Node <= 右子Node,最好情况下二叉搜索的高度为,此时查找、增加、删除的平均时间复杂度为,最差情况下即按照某种顺序插入Node构建的树高度为N,此时增删查的平均时间复杂度为O(N)。代码分为Node类,二叉树抽象类,二叉搜索树实现类。
目录
BinarySearchTree(继承自BinaryTree)
BinaryNode类(简称Node)
Node含有的泛型数据data必须实现Comparable接
口,用来实现Node内部数据的比较,Node本身也实现Comparable接口,两个Node比较时直接调用各自data的compareTo方法。Node也需要包含对父Node以及左右子Node的引用,代码如下:
package TreeStructure;
import org.jetbrains.annotations.NotNull;
public class BinaryNode<T extends Comparable> implements Comparable<BinaryNode<T>> {
private T data;
private BinaryNode<T> parent;
private BinaryNode<T> leftChild;
private BinaryNode<T> rightChild;
public BinaryNode(T data) {
this.data = data;
}
public BinaryNode(T data, BinaryNode<T> parent) {
this.data = data;
this.parent = parent;
}
@Override
public int compareTo(@NotNull BinaryNode<T> tBinaryNode) {
return this.data.compareTo(tBinaryNode.getData());
}
public void visit(){
//节点的访问动作写在这里
System.out.print(data + " ");
}
public boolean hasChild(){
if(this.getLeftChild() == null && this.getRightChild() == null) return false;
else return true;
}
public boolean hasLeftChild(){
if(this.getLeftChild() == null) return false;
return true;
}
public boolean hasRightChild(){
if(this.getRightChild() == null) return false;
return true;
}
public boolean isLeftChildOf(BinaryNode<T> parentBinaryNode){
if(parentBinaryNode != null && parentBinaryNode.getLeftChild() == this)return true;
return false;
}
public boolean isRightChildOf(BinaryNode<T> parentBinaryNode){
if(parentBinaryNode != null && parentBinaryNode.getRightChild() == this)return true;
return false;
}
public BinaryNode<T> getParent() {
return parent;
}
//返回Node右子树中的最小值
public BinaryNode<T> getSuccessor(){
if(rightChild == null) return null;
BinaryNode<T> current = rightChild;
while(current.hasLeftChild())current = current.getLeftChild();
return current;
}
public void setParent(BinaryNode<T> parent) {
this.parent = parent;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public BinaryNode<T> getLeftChild() {
return leftChild;
}
public void setLeftChild(BinaryNode<T> leftChild) {
this.leftChild = leftChild;
}
public BinaryNode<T> getRightChild() {
return rightChild;
}
public void setRightChild(BinaryNode<T> rightChild) {
this.rightChild = rightChild;
}
}
BinaryTree二叉树抽象类(便于后面扩展)
包含一个根Node的引用(root),方法包含增删查以及前中后序遍历,由于二叉树的前中后序遍历方法一样,因此可以直接在该抽象类中实现:
中序遍历
对于一棵以Node为根Node的二叉树,先访问其左子树,再访问root,最后访问右子树,子树的处理方法与树一致,当子树的根Node为Null说明这棵子树是空的,可作为访问完毕的结束条件,从而递归遍历整棵树。
package TreeStructure;
public abstract class BinaryTree<T extends Comparable> {
protected BinaryNode<T> root;
public abstract BinaryNode<T> find(T key);
public abstract void insert(T key);
public abstract void delete(T key);
//从跟Node开始中序遍历
public void inOrder() {
if (root != null) inOrder(root);
}
//从某个Node开始中序遍历
public void inOrder(BinaryNode<T> binaryNode) {
if (binaryNode == null) return;
BinaryNode<T> leftChild = binaryNode.getLeftChild();
BinaryNode<T> rightChild = binaryNode.getRightChild();
if (leftChild != null) inOrder(leftChild);
binaryNode.visit();
if (rightChild != null) inOrder(rightChild);
}
//前序
public void preOrder() {
if (root != null) inOrder(root);
}
public void preOrder(BinaryNode<T> binaryNode) {
if (binaryNode == null) return;
BinaryNode<T> leftChild = binaryNode.getLeftChild();
BinaryNode<T> rightChild = binaryNode.getRightChild();
binaryNode.visit();
if (leftChild != null) preOrder(leftChild);
if (rightChild != null) preOrder(rightChild);
}
//后序
public void postOrder() {
if (root != null) inOrder(root);
}
public void postOrder(BinaryNode<T> binaryNode) {
if (binaryNode == null) return;
BinaryNode<T> leftChild = binaryNode.getLeftChild();
BinaryNode<T> rightChild = binaryNode.getRightChild();
if (leftChild != null) postOrder(leftChild);
if (rightChild != null) postOrder(rightChild);
binaryNode.visit();
}
}
BinarySearchTree(继承自BinaryTree)
查找
假设查找key,若根Node等于key则找到,若根Node比key大则在左子树中找,若根Node大于或等于key则在右子树中找,如果子树为null说明树中不存在key。
插入
插入方法与查找类似,key小于该Node就在左子树中找位置,key大于等于该Node就在右子树中找位置,直到Node的子树为null,该位置即插入位置。
最大/小值
从root开始,按照左子树的方向找下去最后一个Node为最小值,最大值同理。
删除
删除方法较复杂,找到待删除Node后分三种情况:
- 待删除Node不含子Node,则将该Node直接删除。
- 待删除Node含有一个子Node,则将该Node删除后,再把它的父Node与该子Node相连
- 待删除Node含有两个子Node,则在待删除的Node的右子树中找最小值作为Successor,Successor的值覆盖待删除Node后,删除Successor,Successor不可能含有左子树,如果含有左子树,说明还有比Successor小的值,因此删除Successor时用情况1或2的方法即可。
package TreeStructure;
public class BinarySearchTree<T extends Comparable<T>> extends BinaryTree<T> {
@Override
public BinaryNode<T> find(T key) {
if (root == null) return null;
BinaryNode<T> current = root;
while (current.getData().compareTo(key) != 0) {
if (current.getData().compareTo(key) > 0) current = current.getLeftChild();
else current = current.getRightChild();
if (current == null) return null;
}
return current;
}
@Override
public void insert(T key) {
if (root == null)
//树上没有Node直接把root设置为插入Node
root = new BinaryNode<>(key);
else {
//插入Node的父Node
BinaryNode<T> parent;
//遍历Node
BinaryNode<T> current = root;
do {
parent = current;
if (current.getData().compareTo(key) > 0) current = current.getLeftChild();
//相等的Node插入右子树
else current = current.getRightChild();
} while (current != null);
//此时Parent的子Node是null,null用插入Node替代
if (parent.getData().compareTo(key) > 0) parent.setLeftChild(new BinaryNode<>(key, parent));
else parent.setRightChild(new BinaryNode<>(key, parent));
}
}
@Override
public void delete(T key) {
//待删除Node
BinaryNode<T> delete = find(key);
if (delete == null) return;
if (delete.hasChild()) {
if (delete.hasLeftChild() && delete.hasRightChild()) {
//delete有两个Child
BinaryNode<T> successor = delete.getSuccessor();
delete.setData(successor.getData());
if (successor.hasRightChild()) {
//successor有右子节点
successor.getRightChild().setParent(successor.getParent());
if (delete == root) return;
if (successor.isRightChildOf(successor.getParent()))
successor.getParent().setRightChild(successor.getRightChild());
else
successor.getParent().setLeftChild(successor.getRightChild());
} else {
if (successor.isRightChildOf(successor.getParent()))
successor.getParent().setRightChild(null);
else
successor.getParent().setLeftChild(null);
}
} else {
//delete有一个Child
if(delete == root){
//delete是root
if(root.hasLeftChild()) root = root.getLeftChild();
else root = root.getRightChild();
root.setParent(null);
}
else{
//delete的父Node
BinaryNode<T> parent = delete.getParent();
if (delete.isLeftChildOf(parent)) {
if (delete.hasLeftChild()) {
parent.setLeftChild(delete.getLeftChild());
delete.getLeftChild().setParent(parent);
} else {
parent.setLeftChild(delete.getRightChild());
delete.getRightChild().setParent(parent);
}
} else {
if (delete.hasLeftChild()) {
parent.setRightChild(delete.getLeftChild());
delete.getLeftChild().setParent(parent);
} else {
parent.setRightChild(delete.getRightChild());
delete.getRightChild().setParent(parent);
}
}
}
}
} else {
//delete没有子Node(叶子Node)
if (delete == root) root = null;
else{
//delete的父Node
BinaryNode<T> parent = delete.getParent();
if (delete.isLeftChildOf(parent)) parent.setLeftChild(null);
else parent.setRightChild(null);
}
}
}
public BinaryNode<T> minimum() {
if (root == null) return null;
BinaryNode<T> current = root;
while (current.getLeftChild() != null) current = current.getLeftChild();
return current;
}
public BinaryNode<T> maximum() {
if (root == null) return null;
BinaryNode<T> current = root;
while (current.getRightChild() != null) current = current.getRightChild();
return current;
}
}