二叉搜索树
定义
- 首先应该是二叉树;
- 其次某节点左子树键值小于该节点键值,其右子树键值大于等于该节点键值。
基本性质
- 二叉搜索树的基本操作(search、min、max、insert、delete)和树高成正比;
- 随机构造的二叉搜索树,树高期望值为O(log(n)),说明两点:A.无论如何变化,树高在O(log(n))上下变化;B.二叉搜索树可能退化成链表,也就是树高就是节点个数,红黑树就是二叉搜索树的变形,能够确保树高为O(log(n))。
基本操作代码实现
删除
基本操作中删除比较了,可分为三种情况,上图看就明白了:
上图中第三、四行同属一种情况,但四需要先转换成三来处理,即先要将待删除节点的右子树变形为右子树根节点为右子树最小节点。
基本操作代码
import java.util.Random;
public class BinarySearchTree {
private static class Node {
public Node left;
public Node right;
public int key;
public Node pre;
}
private static int[] getRandomInts(int count, int max) {
if (count <= 0 || max <= 0) {
return null;
}
Random random = new Random();
int[] result = new int[count];
for (int i = 0; i < count; i++) {
result[i] = random.nextInt(max);
}
return result;
}
private static Node insertNode(Node root, Node node) {
Node currentPre = null;
Node current = root;
// 找到待插入节点的父节点
while (current != null) {
currentPre = current;
if (current.key < node.key) {
current = current.left;
} else {
current = current.right;
}
}
node.pre = currentPre;
// 待插入节点为树中第一个节点
if (currentPre == null) {
root = node;
return root;
} else {
if (node.key < currentPre.key) {
currentPre.left = node;
} else {
currentPre.right = node;
}
}
return root;
}
private static void transplant(Node root, Node u, Node v) {
if (u.pre == null) {
root = v;
} else if (u == u.pre.left) {
u.pre.left = v;
} else {
u.pre.right = v;
}
if (v != null) {
v.pre = u.pre;
}
}
private static Node minimum(Node node) {
Node currentPre = null;
Node current = node;
while (current != null) {
currentPre = current;
current = current.left;
}
return currentPre;
}
private static void delete(Node root, Node z) {
if (z.left == null) {
transplant(root, z, z.right);
} else if (z.right == null) {
transplant(root, z, z.left);
} else {
Node y = minimum(z.right);
/*
* 如果待删除节点的右子节点不是右子树中最小的(即待删除节点的右子节点有左子节点),需要将待删除节点的右子树变形:
* 找到待删除节点右子树中最小的节点y,删除此节点,并将y插入为待删除节点右子树的根节点
*/
if (y.pre != z) {
transplant(root, y, y.right);
y.right = z.right;
y.right.pre = y;
}
/*
* 统一处理,待删除节点的右子节点为右子树最小节点
*/
transplant(root, z, y);
y.left = z.left;
y.left.pre = y;
}
}
private static Node generateTree(int[] randomInts) {
if (randomInts == null) {
return null;
}
int length = randomInts.length;
Node root = null;
for (int i = 1; i < length; i++) {
Node node = new Node();
node.key = randomInts[i];
root = insertNode(root, node);
}
return root;
}
public static void main(String[] args) {
int[] randomInts = getRandomInts(10, 100);
Node root = generateTree(randomInts);
}
}
参考文档
《算法导论》