二叉排序树
性质
- 二叉排序树是一种特殊的二叉树,它的每个结点都有一个关键字,且满足以下性质:
(1)如果左子树不为空,则左子树上所有结点的关键字都小于根结点的关键字。
(2)如果右子树不为空,则右子树上所有结点的关键字都大于根结点的关键字。
(3)左右子树也都是二叉排序树。
建立、查找、插入和删除
- 二叉排序树的主要操作有建立、查找、插入和删除。
(1)建立二叉排序树是指从一个无序的序列中逐个插入结点,构造出一个二叉排序树。
(2)查找二叉排序树是指从根结点开始,根据关键字和当前结点的比较结果,沿着左右子树递归地查找目标结点,如果找到则返回该结点,否则返回空。
(3)插入二叉排序树是指在查找过程中,如果发现目标关键字不存在,则在最后一个访问的空位置上插入一个新结点,保持二叉排序树的性质不变。
删除二叉排序树是指在查找过程中,如果发现目标关键字存在,则分三种情况处理:
- 如果待删除结点是叶子结点,则直接删除该结点。
- 如果待删除结点只有一个孩子,则用该孩子替换该结点,并删除该结点。
- 如果待删除结点有两个孩子,则用该结点的左子树的最大值或者右子树的最小值替换该结点,并删除原来的最大值或最小值结点。
(4)二叉排序树的优点是查找、插入和删除的时间复杂度都是O(logn),其中n是结点的个数。二叉排序树的缺点是如果序列本身就是有序或者接近有序的,那么构造出来的二叉排序树会退化成链表,导致时间复杂度变成O(n)。为了避免这种情况,可以使用平衡二叉排序树,如AVL树、红黑树等。
代码
//定义二叉排序树节点类
class BSTNode {
int data; //节点存储的数据
BSTNode left; //左子节点
BSTNode right; //右子节点
//构造方法
public BSTNode(int data) {
this.data = data;
this.left = null;
this.right = null;
}
}
//定义二叉排序树类
class BSTree {
BSTNode root; //根节点
//构造方法
public BSTree() {
this.root = null;
}
//插入方法,向二叉排序树中插入一个数据
public void insert(int data) {
//如果根节点为空,直接创建一个新节点作为根节点
if (this.root == null) {
this.root = new BSTNode(data);
return;
}
//否则,从根节点开始遍历,找到合适的位置插入新节点
BSTNode current = this.root; //当前遍历到的节点
BSTNode parent = null; //当前节点的父节点
while (current != null) {
parent = current; //更新父节点
if (data < current.data) { //如果插入的数据小于当前节点的数据,向左子树遍历
current = current.left;
} else if (data > current.data) { //如果插入的数据大于当前节点的数据,向右子树遍历
current = current.right;
} else { //如果插入的数据等于当前节点的数据,不做任何操作,直接返回
return;
}
}
//当遍历结束时,parent指向了插入位置的父节点,current为null
if (data < parent.data) { //如果插入的数据小于父节点的数据,作为父节点的左子节点
parent.left = new BSTNode(data);
} else { //如果插入的数据大于父节点的数据,作为父节点的右子节点
parent.right = new BSTNode(data);
}
}
//中序遍历方法,按照从小到大的顺序输出二叉排序树中的数据
public void inorder() {
inorder(this.root); //从根节点开始遍历
}
//辅助方法,递归地中序遍历以node为根的子树
private void inorder(BSTNode node) {
if (node == null) { //递归基准情形,如果节点为空,直接返回
return;
}
inorder(node.left); //递归地中序遍历左子树
System.out.print(node.data + " "); //输出当前节点的数据
inorder(node.right); //递归地中序遍历右子树
}
}
//测试代码
public class TestBSTree {
public static void main(String[] args) {
BSTree tree = new BSTree(); //创建一个空的二叉排序树对象
tree.insert(5); //向二叉排序树中插入一些数据
tree.insert(3);
tree.insert(7);
tree.insert(2);
tree.insert(4);
tree.insert(6);
tree.insert(8);
tree.inorder(); //中序遍历二叉排序树,输出结果应为2 3 4 5 6 7 8
}
}
这个代码主要分为两个类,一个是BSTNode,表示二叉排序树的节点,一个是BSTree,表示二叉排序树本身。BSTNode类有三个属性,分别是data,left和right,分别表示节点存储的数据,左子节点和右子节点。BSTNode类有一个构造方法,用于创建一个新的节点,并给定数据。BSTree类有一个属性,就是root,表示二叉排序树的根节点。BSTree类有两个主要的方法,一个是insert,用于向二叉排序树中插入一个数据,一个是inorder,用于按照从小到大的顺序输出二叉排序树中的数据。