package com.dataStructure.searchTree;
/**
* 二叉查找树,对于其中的任何一个结点x,如果y是x左子树中的一个结点,那么y的关键字一定不大于x的关键字;
* 如果y是x右子树中的一个结点,那么y的关键字一定不小于x的关键字
*/
public class BinarySearchTree {
private static Node root = null;
private class Node{
private int key;
private Node leftChild;
private Node rightChild;
private Node parent;
public Node(int key, Node leftChild, Node rightChild, Node parent){
this.key = key;
this.leftChild = leftChild;
this.rightChild = rightChild;
this.parent = parent;
}
}
public static Node getRoot(BinarySearchTree tree){
return root;
}
/**
* 插入关键字key
*/
public void insert( int key) {
Node y = null;
Node x = root;//指向根结点
Node node = new Node(key, null, null, null);
//while循环结束的时候,x指向空结点,y指向待插入结点的双亲
while(x != null){
y = x;//y指向双亲结点
if(node.key < x.key){
x = x.leftChild;
}else{
x = x.rightChild;
}
}
//将待插入结点的双亲赋值为y结点
node.parent = y;
//如果y为空,说明树为空
if(y == null){
root = node;
}else{
//根据关键字的大小,将y插入到合适的地方
if (node.key < y.key) {
y.leftChild = node;
}else{
y.rightChild = node;
}
}
}
/**
* 删除关键字key所对应的结点,对应3种不同的情况
* 1、结点没有孩子,则可以直接删除该结点,将该结点的双亲结点对应的孩子指针置为null
* 2、结点只有一个孩子,则可以将结点的孩子直接连到结点的双亲结点上,作为双亲结点的孩子,然后删除该结点
* 3、结点有两个孩子,则需要删除的是结点的后继结点,将后继结点的数据拷贝到该结点内,同时后继结点的孩子作为后继结点双亲结点的孩子,
* 因为后继结点最后只有一个子女
*/
public void delete(int key){
Node z = tree_search(root, key);
if(z == null){
return;
}else{
Node x = new Node(0, null, null, null);
Node y = new Node(0, null, null, null);
if(z.leftChild == null || z.rightChild == null){
y = z;
}else{
y = tree_successor(z);
}
if(y.leftChild != null){
x = y.leftChild;
}else{
x = y.rightChild;
}
if(x != null){
x.parent = y.parent;
}
if(y.parent == null){
root = x;
}else{
if(y==(y.parent).leftChild){
(y.parent).leftChild = x;
}else{
(y.parent).rightChild = x;
}
}
if(y != z){
z.key = y.key;
}
}
}
/**
* 判断二叉查找树是否为空
*/
public static boolean isEmpty(BinarySearchTree tree){
if (BinarySearchTree.root == null) {
return true;
}else{
return false;
}
}
/**
* 中序遍历二叉查找树
*/
public static void inorder_tree_walk(Node tree){
if(tree != null){
inorder_tree_walk(tree.leftChild );
System.out.print(tree.key + " " );
inorder_tree_walk(tree.rightChild);
}
}
/**
* 查找关键字为key的结点(递归查找)
*/
public Node tree_search(Node root, int key){
if(root == null || key == root.key){
return root;
}
if(root.key < key){
return tree_search(root.rightChild, key);
}else{
return tree_search(root.leftChild, key);
}
}
/**
* 查找关键字为key的结点(非递归查找)
*/
public Node iterative_tree_search(Node root, int key){
while(root != null && key!= root.key){
if(key< root.key){
root = root.leftChild;
}else{
root = root.rightChild;
}
}
return root;
}
/**
* 查找最小关键字元素,查找方法:
* 从根节点开始,沿着各结点的左孩子指针查找下去,直至遇到空为止
*/
public Node tree_minimum(Node root){
while(root.leftChild != null){
root = root.leftChild;
}
return root;
}
/**
* 查找最大关键字元素
*/
public Node tree_maximum(Node root){
while(root.rightChild != null){
root = root.rightChild;
}
return root;
}
/**
* 查找元素的后继
*/
public Node tree_successor(Node node){
//如果结点的右子树不为空,则x的后继即为右子树中的最左结点,也即右子树中的最小结点
if(node.rightChild != null){
return tree_minimum(node.rightChild);
}
//如果结点的右子树为空,且有一个后继y, 则y是该结点的最低祖先节点,且y的左儿子也是该结点的祖先
Node yNode = node.parent;
while(yNode != null && node == yNode.rightChild){
node = yNode;
yNode = yNode.parent;
}
return yNode;
}
/**
* 查找元素的前驱
*/
public Node tree_precorsor(Node node){
if(node.leftChild != null){
return tree_maximum(node.leftChild);
}
Node yNode = node.parent;
while(yNode!=null && node == yNode.leftChild){
node = yNode;
yNode = yNode.parent;
}
return yNode;
}
/**
* 测试
*/
public static void main(String[] args) {
//构建二叉查找树
BinarySearchTree tree = new BinarySearchTree();
int[] keys = {18, 5, 6, 3, 12, 20, 2, 4, 13, 9};
for(int i = 0;i<keys.length; i++){
tree.insert(keys[i]);
}
inorder_tree_walk(root);
System.out.println();
//查找关键字18
Node _18Node = tree.tree_search(root, 18);
if(_18Node == null){
System.out.println("不存在关键字18");
}else{
System.err.println("查找到关键字18");
}
//查找关键字19
Node _19Node = tree.iterative_tree_search(root, 19);
if(_19Node == null){
System.out.println("不存在关键字19");
}else{
System.err.println("查找到关键字19");
}
//查找最小关键字元素
Node minNode = tree.tree_minimum(root);
System.out.println("最小值为:" + minNode.key);
//查找最大关键字元素
Node maxNode = tree.tree_maximum(root);
System.out.println("最大值为:" + maxNode.key);
//查找元素13的后继
Node _13Node = tree.tree_search(root, 13);
Node _13Successor = tree.tree_successor(_13Node);
System.out.println("元素13的后继元素的关键字为:" + _13Successor.key);
//查找元素13的前驱
Node _13Precursor = tree.tree_precorsor(_13Node);
System.out.println("元素13的前驱元素的关键字为:" + _13Precursor.key);
//删除元素13,对应第一种情况
tree.delete(13);
inorder_tree_walk(root);
System.out.println();
//删除关键字19,对应找不到该结点的情况
tree.delete(19);
inorder_tree_walk(root);
System.out.println();
//删除关键字6,对应第二种情况
tree.delete(6);
inorder_tree_walk(root);
System.out.println();
//删除元素5,对应第三种情况
tree.delete(5);
inorder_tree_walk(root);
}
}