树-二叉循环树
什么是二叉搜索树
二叉搜索树(Binary Search Tree),是最基础,且相对简单的一种数据结构,支持Insert,Delete,Search,Min,Max,Successor,Predecessor等操作。最大的特点是每一个节点有不超过两个子节点,并且左子节点小于或者等于父节点,而右节点大于或者等于父节点。说它基础,是因为很多其它树形数据结构以它为原型而扩展,比如红黑树,B树。
二叉搜索树:
1.所有非叶子结点至多拥有两个儿子(Left和Right);
2.所有结点存储一个关键字;
3.非叶子结点的左指针指向小于其关键字的子树,右指针指向大于其关键字的子树;
如:
B树的搜索,从根结点开始,如果查询的关键字与结点的关键字相等,那么就命中;
否则,如果查询关键字比结点关键字小,就进入左儿子;如果比结点关键字大,就进入
右儿子;如果左儿子或右儿子的指针为空,则报告找不到相应的关键字;
如果B树的所有非叶子结点的左右子树的结点数目均保持差不多(平衡),那么B树
的搜索性能逼近二分查找;但它比连续内存空间的二分查找的优点是,改变B树结构
(插入与删除结点)不需要移动大段的内存数据,甚至通常是常数开销;
如:
但B树在经过多次插入与删除后,有可能导致不同的结构:
右边也是一个B树,但它的搜索性能已经是线性的了;同样的关键字集合有可能导致不同的
树结构索引;所以,使用B树还要考虑尽可能让B树保持左图的结构,和避免右图的结构,也就
是所谓的“平衡”问题;
实际使用的B树都是在原B树的基础上加上平衡算法,即“平衡二叉树”;如何保持B树
结点分布均匀的平衡算法是平衡二叉树的关键;平衡算法是一种在B树中插入和删除结点的
策略;
package com.qjm.xj.action;
/**
* 二叉树:删除头结点,会从左节点或者右结点拿一个作为头结点
*
* **/
public class BinaryTree<T extends Comparable<T>> {
private Node<T> root;
public void insert(T element) {
if (element == null) {
throw new IllegalArgumentException("element can not be null");
}
if (root == null) { //如果root=null,就是第一个结点,就创建结点。
root = new Node<T>(null, element);
} else {
Node<T> node = root;
while (true) {
if (element.compareTo(node.value) <= 0) { //字符串比较,"a".compareTo("b") >0
if (node.left == null) {
Node<T> newNode = new Node<T>(node, element);
node.left = newNode;
break;
} else {
node = node.left;
}
} else {
if (node.right == null) {
Node<T> newNode = new Node<T>(node, element);
node.right = newNode;
break;
} else {
node = node.right;
}
}
}
}
}
private int childCount(Node<T> node) {
if (node == null) {
throw new IllegalArgumentException("node can not be null");
}
int count = 0;
if (node.left != null) {
count++;
}
if (node.right != null) {
count++;
}
return count;
}
public void delete(Node<T> node) {
if (node == null) {
throw new IllegalArgumentException("node can not be null");
}
int childCount = childCount(node); //查看是否有左右结点
Node<T> parentNode = node.parent;
if (childCount == 0) {
if (parentNode == null) {
// node is root
root = null;
} else {
if (node == parentNode.left) {
parentNode.left = null;
} else {
parentNode.right = null;
}
}
} else if (childCount == 1) {
if (parentNode == null) {
// node is root, set child of node to be new root
if (node.left != null) {
root = node.left; //如果当前结点的左节点不为空,就把左节点赋给一个Node,然后让Node的左节点的父节点置为空
node.left.parent = null;
} else {
root = node.right;
node.right.parent = null;
}
} else {
if (node == parentNode.left) {
if (node.left != null) {
parentNode.left = node.left;
node.left.parent = parentNode;
} else {
parentNode.left = node.right;
node.right.parent = parentNode;
}
} else {
if (node.left != null) {
parentNode.right = node.left;
node.left.parent = parentNode;
} else {
parentNode.right = node.right;
node.right.parent = parentNode;
}
}
}
} else {
// successor has no left child
Node<T> successor = min(node); //获取最小的左节点
if (successor != node.right) {
transplant(successor, successor.right);
successor.right = node.right;
node.right.parent = successor;
}
transplant(node, successor);
successor.left = node.left;
node.left.parent = successor;
}
}
/**
* param1:当前结点
* param12:最小左节点(最小结点)
* 替换,把要删除的结点的左右结点指向删除结点的父节点
* **/
private void transplant(Node<T> u, Node<T> v) {
if (u == null) {
throw new IllegalArgumentException("node can not be null");
}
if (u.parent == null) {
root = v;
} else if (u == u.parent.left) {
u.parent.left = v;
} else {
u.parent.right = v;
}
if (v != null) {
v.parent = u.parent;
}
}
public Node<T> search(T element) {
if (element == null) {
throw new IllegalArgumentException("element can not be null");
}
Node<T> node = root;
while (node != null) {
if (node.value.equals(element)) { //先查找是否等于当前结点
return node;
} else if (element.compareTo(node.value) < 0) {//如果小于结点,就查找它的左孩子,并把左孩子赋给当前孩子,做循环查找
node = node.left;
} else {
node = node.right; //反正查找右结点
}
}
return null;
}
public Node<T> min(Node<T> rootNode) {
if (rootNode == null) {
throw new IllegalArgumentException("node can not be null");
}
Node<T> node = rootNode;
while (node.left != null) {
node = node.left;
}
return node;
}
public Node<T> min() {
if (root != null) {
return min(root);
} else {
return null;
}
}
public Node<T> max(Node<T> rootNode) {
if (rootNode == null) {
throw new IllegalArgumentException("node can not be null");
}
Node<T> node = rootNode;
while (node.right != null) {
node = node.right;
}
return node;
}
public Node<T> max() {
if (root != null) {
return max(root);
} else {
return null;
}
}
public Node<T> successor(Node<T> node) {
if (node == null) {
throw new IllegalArgumentException("node can not be null");
}
if (node.right != null) {
return min(node.right);
}
Node<T> processNode = node;
Node<T> parent = processNode.parent;
while (parent != null && processNode == parent.right) {
processNode = parent;
parent = processNode.parent;
}
return parent;
}
public Node<T> predecesssor(Node<T> node) {
if (node == null) {
throw new IllegalArgumentException("node can not be null");
}
if (node.left != null) {
return max(node.left);
}
Node<T> processNode = node;
Node<T> parent = processNode.parent;
while (parent != null && processNode == parent.left) {
processNode = parent;
parent = processNode.parent;
}
return parent;
}
public void print() {
print(root);
}
//这个查找非常经典
public void print(Node<T> node) {
if (node == null) {
return;
}
print(node.left);
System.out.print(" " + node.value.toString() + " ");
print(node.right);
}
public static class Node<T extends Comparable<T>> {
private Node<T> parent;//父节点
private Node<T> left; //左孩子
private Node<T> right; //右孩子
private T value; //值
public Node(Node<T> parent, T value) {
this.parent = parent;
this.value = value;
}
public Node<T> getParent() {
return parent;
}
public void setParent(Node<T> parent) {
this.parent = parent;
}
public Node<T> getLeft() {
return left;
}
public void setLeft(Node<T> left) {
this.left = left;
}
public Node<T> getRight() {
return right;
}
public void setRight(Node<T> right) {
this.right = right;
}
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
}
public static void main(String[] args) {
BinaryTree<String> tree = new BinaryTree<String>();
tree.insert("Hello");
tree.insert("World");
tree.insert("Money");
tree.insert("Money");
tree.insert("Loney");
tree.insert("Aoney");
tree.insert("Doney");
tree.insert("Xoney");
tree.insert("Noney");
tree.print();
System.out.println();
Node<String> moneyNode = tree.search("Money");
tree.print(moneyNode);
System.out.println("**************");
tree.insert("Like");
tree.print(moneyNode);
System.out.println();
tree.delete(moneyNode);
tree.print();
System.out.println();
}
}
本文转载至:http://blog.csdn.net/kimylrong/article/details/21872909