本帖部分文字和图片来自于
https://zh.wikipedia.org/wiki/%E4%BA%8C%E5%85%83%E6%90%9C%E5%B0%8B%E6%A8%B9
http://www.cnblogs.com/huangxincheng/archive/2012/07/21/2602375.html
但所有代码均为原创
二叉查找树(英语:Binary Search Tree),也称二叉搜索树、有序二叉树(英语:ordered binary tree),排序二叉树(英语:sorted binary tree),是指一棵空树或者具有下列性质的二叉树:
- 若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
- 若任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
- 任意节点的左、右子树也分别为二叉查找树;
- 没有键值相等的节点。
二叉查找树相比于其他数据结构的优势在于查找、插入的时间复杂度较低,为O(log n)。二叉查找树是基础性数据结构,用于构建更为抽象的数据结构,如集合、multiset、关联数组等。
如何添加元素到二叉查询树中呢?
- 若b是空树,则将s所指结点作为根节点插入,否则:
- 若s->data等于b的根节点的数据域之值,则返回,否则:
- 若s->data小于b的根节点的数据域之值,则把s所指节点插入到左子树中,否则:
- 把s所指节点插入到右子树中。(新插入节点总是叶子节点)
首先定义二叉查找树类
public class BinarySearchTreeNode {
public int value = 0;
public BinarySearchTreeNode parent = null;
public BinarySearchTreeNode left = null;
public BinarySearchTreeNode right = null;
public BinarySearchTreeNode(int value){
this.value = value;
}
}
然后定义add方法
public BinarySearchTreeNode add(int value, BinarySearchTreeNode node){
if(node == null) {
node = new BinarySearchTreeNode(value);
}else {
if (value< node.value) {
node.left = add(value, node.left);
} else {
node.right = add(value, node.right);
}
}
打印整个二叉查找树:
public void printBST(BinarySearchTreeNode node){
System.out.print("node = " + node.value);
System.out.print(", node.parent = " + (node.parent==null?"null":node.parent.value));
System.out.print(", left=" + (node.left==null?"null":node.left.value));
System.out.print(", right=" + (node.right==null?"null":node.right.value));
System.out.println("");
if(node.left != null){
printBST(node.left);
}
if(node.right != null){
printBST(node.right);
}
}
最后我们运行下面的代码进行测试:
int[] values = {20,15,25,10,18,30,12};
BinarySearchTreeNode root = null;
for(int i=0; i<values.length; i++) {
root = add(values[i], root);
}
printBST(root);
以下是输出内容:
node = 20, node.parent = null, left=15, right=25
node = 15, node.parent = 20, left=10, right=18
node = 10, node.parent = 15, left=null, right=12
node = 12, node.parent = 10, left=null, right=null
node = 18, node.parent = 15, left=null, right=null
node = 25, node.parent = 20, left=null, right=30
node = 30, node.parent = 25, left=null, right=null
生成二叉查找树的问题解决了,那么如何查找呢
- 若b是空树,则搜索失败,否则:
- 若x等于b的根节点的数据域之值,则查找成功;否则:
- 若x小于b的根节点的数据域之值,则搜索左子树;否则:
- 查找右子树。
public BinarySearchTreeNode search(BinarySearchTreeNode node, int value){
if(node != null) {
if(value == node.value){
return node;
}else if (value < node.value) {
return search(node.left, value);
} else {
return search(node.right, value);
}
}else{
return null;
}
}
>
System.out.println(“search 18 = ” + (search(root, 18)==null?”failure”:”success”));
System.out.println(“search 22 = ” + (search(root, 22)==null?”failure”:”success”));
输出结果:
search 18 = success
search 22 = failure
删除是最复杂的,主要考虑两种情况
单孩子的情况
这个比较简单,如果删除的节点有左孩子那就把左孩子顶上去,如果有右孩子就把右孩子顶上去,结束。
左右都有孩子的情况
首先可以这么想象,如果我们要删除一个数组的元素,那么我们在删除后会将其后面的一个元素顶到被删除的位置,如图
那么二叉树操作同样也是一样,我们根据”中序遍历“找到要删除结点的后一个结点,然后顶上去就行了,原理跟”数组”一样一样的。
代码如下:
public BinarySearchTreeNode delete(BinarySearchTreeNode node){
if(node != null){
if (node.left == null && node.right == null) {
if(node.parent == null){
node = null;
return node;
} else if (node.parent.left != null && node.parent.left.value == node.value) {
node.parent.left = null;
} else if (node.parent.right != null && node.parent.right.value == node.value) {
node.parent.right = null;
}
return node.parent;
} else if (node.left != null && node.right != null) {
node.value = node.right.value;
node = delete(node.right);
} else {
BinarySearchTreeNode parent = node.parent;
BinarySearchTreeNode n = node.left == null ? node.right : node.left;
n.parent = parent;
if (node.parent.left != null && node.parent.left.value == node.value) {
node.parent.left = n;
} else if (node.parent.right != null && node.parent.right.value == node.value) {
node.parent.right = n;
}
node = n;
}
}
return node;
}
以下是测试代码:
System.out.println("it will delete 15");
BinarySearchTreeNode deleteNode15 = search(root, 15);
if(deleteNode15 != null && deleteNode15.parent != null) {
System.out.println("delete 15 = " + (delete(deleteNode15) == null ? "failure" : "success"));
}else{
deleteNode15 = null;
System.out.println("There is no any node.");
}
printBST(root);
it will delete 15
delete 15 = success
node = 20, node.parent = null, left=18, right=25
node = 18, node.parent = 20, left=10, right=null
node = 10, node.parent = 18, left=null, right=12
node = 12, node.parent = 10, left=null, right=null
node = 25, node.parent = 20, left=null, right=30
node = 30, node.parent = 25, left=null, right=null