Java实现 二叉搜索树算法(BST)
树是由节点和边构成,储存元素的集合。节点分根节点、父节点和子节点的概念。二叉树binary tree,则加了“二叉”(binary),意思是在树中作区分。 每个节点至多有两个子(child),left child & right child。二叉树在很多例子中使用,比如二叉树表示算术表达式。 其要求:每个节点比其左子树元素大,比其右子树元素小。
1、对其节点的増差删:
package com.cxg.demo.test.tree;
/**
* Title: Java实现 二叉搜索树算法(BST)</br>
* 树是由节点和边构成,储存元素的集合。节点分根节点、父节点和子节点的概念。
* 二叉树binary tree,则加了“二叉”(binary),意思是在树中作区分。
* 每个节点至多有两个子(child),left child & right child。
* 二叉树在很多例子中使用,比如二叉树表示算术表达式。
* 其要求:每个节点比其左子树元素大,比其右子树元素小。
* Description: TestDemo</br>
* @author xg.c
* @date 2016年7月26日 上午10:11:37
*/
public class BinarySearchTree {
//常量之根节点
public static TreeNode root;
public BinarySearchTree() {
this.root = null;
}
/**
* Title: 打印二叉树</br>
* Description: TestDemo</br>
* @author xg.c
* @date 2016年7月26日 上午10:53:13
* @param root
*/
public void toString(TreeNode root) {
if (root != null) {
toString(root.left);
System.out.print("value = " + root.value + " -> ");
toString(root.right);
}
}
/**
* Title: 添加节点</br>
* 要求:每个节点比其左子树元素大,比其右子树元素小。</br>
* 步骤:
* 1. 从root节点开始
* 2. 如果root为空,root为插入值
* 循环:
* 3. 如果当前节点值大于插入值,找左节点
* 4. 如果当前节点值小于插入值,找右节点
* Description: TestDemo</br>
* @author xg.c
* @date 2016年7月26日 上午10:25:08
* @param key 插入的节点值
* @return 新的二叉树
*/
public TreeNode inster(int key){
//新增的节点
TreeNode newNode=new TreeNode(key);
//根节点
TreeNode current=root;
//父节点
TreeNode parent=null;
//如果根节点是空的,那么新增的节点就是当根节点
if (current==null) {
root=newNode;
return newNode;
}
//如果根节点不为空
//循环
while (true) {
parent=current;
if (key<current.value) {//如果当前节点值大于插入值,找左节点
current=current.left;
if (current==null) {
parent.left=newNode;
return newNode;
}
} else {//如果当前节点值小于插入值,找右节点
current=current.right;
if (current==null) {
parent.right=newNode;
return newNode;
}
}
}
}
/**
* Title: 查找节点</br>
* 其算法复杂度 : O(lgN),树深(N)
* 步骤:
* 1. 从root节点开始
* 2. 比当前节点值小,则找其左节点
* 3. 比当前节点值大,则找其右节点
* 4. 与当前节点值相等,查找到返回TRUE
* 5. 查找完毕未找到
* Description: TestDemo</br>
* @author xg.c
* @date 2016年7月26日 上午11:00:34
* @param key 查找的节点
* @return 返回查找值
*/
public TreeNode search(int key){
//根节点
TreeNode current=root;
//循环
while(current!=null && key!=current.value){
if (key<current.value) {//比当前节点值小,则找其左节点
current=current.left;
} else {//比当前节点值大,则找其右节点
current=current.right;
}
}
return current;
}
/**
* Title: 删除节点
* 步骤:
* 1.找到删除节点
* 2.如果删除节点左节点为空 , 右节点也为空;
* 3.如果删除节点只有一个子节点 右节点 或者 左节点
* 4.如果删除节点左右子节点都不为空
* @author: xg.chen
* @param key 删除的节点
* @return
*/
public TreeNode delete (int key) {
TreeNode parent = root;
TreeNode current = root;
boolean isLeftChild = false;
// 找到删除节点 及 是否在左子树
while (current.value != key) {
parent = current;
if (current.value > key) {
isLeftChild = true;
current = current.left;
} else {
isLeftChild = false;
current = current.right;
}
if (current == null) {
return current;
}
}
// 如果删除节点左节点为空 , 右节点也为空
if (current.left == null && current.right == null) {
if (current == root) {
root = null;
}
// 在左子树
if (isLeftChild == true) {
parent.left = null;
} else {
parent.right = null;
}
}
// 如果删除节点只有一个子节点 右节点 或者 左节点
else if (current.right == null) {
if (current == root) {
root = current.left;
} else if (isLeftChild) {
parent.left = current.left;
} else {
parent.right = current.left;
}
}
else if (current.left == null) {
if (current == root) {
root = current.right;
} else if (isLeftChild) {
parent.left = current.right;
} else {
parent.right = current.right;
}
}
// 如果删除节点左右子节点都不为空
else if (current.left != null && current.right != null) {
// 找到删除节点的后继者
TreeNode successor = getDeleteSuccessor(current);
if (current == root) {
root = successor;
} else if (isLeftChild) {
parent.left = successor;
} else {
parent.right = successor;
}
successor.left = current.left;
}
return current;
}
/**
* Title: 获取删除节点的后继者,删除节点的后继者是在其右节点树种最小的节点
* @author: xg.chen
* @param deleteNode 删除的节点
* @return
*/
public TreeNode getDeleteSuccessor(TreeNode deleteNode) {
// 后继者
TreeNode successor = null;
TreeNode successorParent = null;
TreeNode current = deleteNode.right;
while (current != null) {
successorParent = successor;
successor = current;
current = current.left;
}
// 检查后继者(不可能有左节点树)是否有右节点树
// 如果它有右节点树,则替换后继者位置,加到后继者父亲节点的左节点.
if (successor != deleteNode.right) {
successorParent.left = successor.right;
successor.right = deleteNode.right;
}
return successor;
}
}
2、节点的数据接口
package com.cxg.demo.test.tree;
/**
* Title: 节点的数据接口,节点分左节点和右节点及本身节点值</br>
* Description: TestDemo</br>
* @author xg.c
* @date 2016年7月26日 上午10:15:46
*/
public class TreeNode {
//节点的值
int value;
//左节点
TreeNode left;
//右节点
TreeNode right;
//节点的构造方法
public TreeNode(int value) {
this.value = value;
left = null;
right = null;
}
}
3、测试单元
package com.cxg.demo.test.tree;
/**
* Title: BST算法测试</br>
* Description: TestDemo</br>
* @author xg.c
* @date 2016年7月26日 上午10:44:46
*/
public class TestBST {
public static void main(String[] args) {
BinarySearchTree bst=new BinarySearchTree();
//插入节点并打印数组
bst.inster(3);
bst.inster(5);
bst.inster(2);
bst.inster(6);
bst.inster(4);
bst.inster(8);
bst.inster(20);
bst.inster(21);
bst.inster(33);
bst.toString(bst.root);
System.out.println();
//查询是否存在此节点
TreeNode node=bst.search(8);
System.out.println("是否存在节点值为8 => " + node.value);
//删除节点
TreeNode node1=bst.delete(8);
System.out.println("删除后的树型节点为:"+node1.value);
bst.toString(bst.root);
System.out.println();
}
}