具有以下特征的可以被定义为二叉查找树(Binary Search Tree):
(1)若左子树不空,则左子树上所有结点的值均小于它的根节点 的值;(2)若右子树不空,则右子树上所有结点的值均大于或等于它的根结点的值;
(3)中序遍历可以让节点有序
二叉查找树适用于范围查找,这个才是我们使用二叉树的最终目的,既然是范围查找,我们就知道了一个”min“和”max“,其实实现起来也很简单,
第一步:我们要在树中找到min元素,当然min元素可能不存在,但是我们可以找到min的上界,耗费时间为O(logn)。
第二步:从min开始我们中序遍历寻找max的下界。耗费时间为m。m也就是匹配到的个数。
二叉查找树的插入:
1.先执行查找,找到要插入元素位置的父节点
2.判断其是父节点的左叶子/右叶子,被插入节点做为叶子节点插入
二叉查找树的删除:
1.根据给定的key值找到要被删除的节点p,判断是否是叶子节点(是则直接删除)
2.判断其是否有左孩子,如果有则找到左孩子的最右节点r,将r的(key,value)数据覆盖p的(key,value)数据,没有则直接使用右孩子覆盖p
3.判断r是否等于p的左孩子节点,是则将p的左孩子指向r的左孩子,不是则将r的父节点的右孩子指向r(左儿子的最右节点)的左孩子
下面是一个查找二叉树的实现:
package test;
import java.util.Random;
public class BinaryTreeTest {
private static class BinaryNode implements Comparable<BinaryNode> {
// 节点
private String key;
// 数量
private int total;
// 左子节点
private BinaryNode leftNode;
// 右子节点
private BinaryNode rightNode;
// 父节点
private BinaryNode parentNode;
public BinaryNode getParentNode() {
return parentNode;
}
public void setParentNode(BinaryNode parentNode) {
this.parentNode = parentNode;
}
public BinaryNode getLeftNode() {
return leftNode;
}
public void setLeftNode(BinaryNode leftNode) {
leftNode.setParentNode(this);
this.leftNode = leftNode;
}
public BinaryNode getRightNode() {
return rightNode;
}
public void setRightNode(BinaryNode rightNode) {
rightNode.setParentNode(this);
this.rightNode = rightNode;
}
public BinaryNode(String key) {
this.key = key;
total = 1;
}
public int compareTo(BinaryNode o) {
int result = (o.getKey()).compareTo(key);
if(result == 0){
return 0;
}else if(result < 0){
return -1;
}else if(result > 0){
return 1;
}
return 0;
}
public int compareTo(String k) {
int result = k.compareTo(key);
if(result == 0){
return 0;
}else if(result > 0){
return -1;
}else if(result < 0){
return 1;
}
return 0;
}
public void increament() {
total++;
}
public String getKey() {
return this.key;
}
public void setKey(String key) {
this.key = key;
}
}
public static void addChildNode(BinaryNode startNode,BinaryNode addNode){
int compare = addNode.compareTo(startNode);
switch (compare) {
//相等,则当前节点数量+1
case 0:
startNode.increament();
break;
//大于则找到其右子节点,并继续执行添加过程
case 1:
BinaryNode rightNode = startNode.getRightNode();
if(rightNode == null){
startNode.setRightNode(addNode);
}else{
addChildNode(rightNode, addNode);
}
break;
//小于则找到其左子节点继续执行添加过程
case -1:
BinaryNode leftNode = startNode.getLeftNode();
if(leftNode == null){
startNode.setLeftNode(addNode);
}else{
addChildNode(leftNode, addNode);
}
break;
default:
break;
}
}
public static BinaryNode sercherChildNode(BinaryNode startNode,String sercherKey){
int compare = startNode.compareTo(sercherKey);
switch (compare) {
//相等,则当前节点数量+1
case 0:
return startNode;
//大于则找到其右子节点,并继续执行添加过程
case 1:
return sercherChildNode(startNode.getRightNode(), sercherKey);
//小于则找到其左子节点继续执行添加过程
case -1:
return sercherChildNode(startNode.getLeftNode(), sercherKey);
}
return null;
}
/**
* 1.若p有左子树,找到其左子树的最右边的结点r,用该结点r来替代p,把r的左孩子
* 作为r的父亲的右孩子。
* 2.若p没有左子树,直接用p的右孩子取代它。
*/
public static BinaryNode deleteChildNode(BinaryNode startNode,String key){
BinaryNode node = sercherChildNode(startNode, key);
if(node != null){
BinaryNode left = node.getLeftNode();
if(left != null){
//查找最右的节点
BinaryNode pre = left;
while(pre.getRightNode()!=null){
pre = pre.getRightNode();
}
node.setKey(pre.getKey());
//如果pre是node的左子树,则把node的左子树设置成pre的左子树
if(pre.compareTo(left) == 0){
node.setLeftNode(pre.getLeftNode());
}else{
//把pre节点的父节点的右子树 设置成pre的左子树
pre.getParentNode().setRightNode(pre.getLeftNode());
}
}else{
//左子树为空,则直接设置node为右子树
node = node.getRightNode();
}
}
return null;
}
//随机生成一个1-10长度的字符串
public static String genStr() {
StringBuffer buffer = new StringBuffer("");
Random random = new Random();
int strLength = random.nextInt(10);
strLength = strLength==0?1:strLength;
for(int i =0;i<strLength;i++){
char r = (char)(random.nextInt(82)+40);
buffer.append(r);
}
return buffer.toString();
}
}