首先是Node 类的定义
package SearchTree;
public class Node {
private Node left;
private Node right;
private Node Parrent;
int data;
public Node(Node left, Node right, Node parrent, int data) {
super();
this.left = left;
this.right = right;
Parrent = parrent;
this.data = data;
}
public void setLeft(Node left) {
this.left = left;
}
public void setRight(Node right) {
this.right = right;
}
public void setParrent(Node parrent) {
Parrent = parrent;
}
public void setData(int data) {
this.data = data;
}
public Node getLeft() {
return left;
}
public Node getRight() {
return right;
}
public Node getParrent() {
return Parrent;
}
public int getData() {
return data;
}
}
接着是,Tree 类的定义(各种常用的操作)
package SearchTree;
public class Tree {
private Node boot=null; // 二叉查找树的根节点
public Node getBoot() {
return boot;
}
public void setBoot(Node boot) {
this.boot = boot;
}
public void Tree_Insert(Node i_node) // 在树中插入一个节点 i_node
{
Node y = null;
Node x = boot;
while(x!=null)
{
y = x;
if(i_node.getData() < x.getData())
x = x.getLeft();
else x = x.getRight();
}
i_node.setParrent(y); // 设置插入节点的 父节点
if(y == null) // This Tree is empty;
{
boot = i_node;
}
else if(y.getData() > i_node.getData())
y.setLeft(i_node);
else y.setRight(i_node);
}
public void InOrder_Tree_Walk() // 中序遍历输出树
{
Traversal(boot);
}
private void Traversal(Node x)
{
if(x!=null)
{
Traversal(x.getLeft());
System.out.println(x.getData());
Traversal(x.getRight());
}
}
public Node Tree_Search(int data)
{
// Node find =RecursionSearch(boot, data); // 递归的查找
Node find = Non_RecursionSearch(boot, data); // 非递归的查找
if(find == null)
System.out.println("Warning:The element that you are searching is not in the tree!");
else System.out.println("find the element in the tree!");
return find;
}
private Node RecursionSearch(Node b,int data)
{
if(b==null || b.getData()==data) // | 和 || 两者之间什么关系 ?
return b;
if(b.getData() < data)
return RecursionSearch(b.getRight(), data);
else return RecursionSearch(b.getLeft(), data);
}
private Node Non_RecursionSearch(Node b,int data) // 非递归的查找的实现
{
while(b!=null && b.getData()!=data)
{
if(b.getData() > data)
b = b.getLeft();
else b = b.getRight();
}
return b;
}
/***
* 返回树中最小的元素 ,如果树为空的话,返回空的引用
* @return
*/
public Node Tree_Minmum()
{
if(boot==null)
return null;
Node find = minmum(boot);
return find;
}
private Node minmum(Node x)
{
while(x.getLeft()!=null)
x= x.getLeft();
return x;
}
/**
* 返回树中最大的元素,如果树为空的话,返回空的引用
* @return
*/
public Node Tree_Maximum()
{
if(boot == null)
return boot;
Node find = Maximum(boot);
return find;
}
private Node Maximum(Node x)
{
while(x.getRight()!=null)
x = x.getRight();
return x;
}
/**
* 查找一个给定元素data的后继(如果该元素存在的话)
* 存在两种情景:1:存在右孩子,则求右孩子的minmum即可
* 2: 不存在右孩子,那么向上循环查找一个父节点,它的左孩子等于循环中的x,此时该点为其后继
* @param data
* @return
* while 循环是本函数的核心代码(难点)
*/
public Node Tree_Successor(int data)
{
Node x= Tree_Search(data); // 获得元素data 的节点引用。
if(x==null) return null;
if(x.getRight()!=null)
return minmum(x.getRight());
Node y = x.getParrent();
while(y!=null && x==y.getRight())
{
x=y;
y= y.getParrent();
}
return y;
}
/**
* Funtion:查找一个给定元素的中序遍历的前驱节点,有两种情况:
* 1:该节点存在左孩子,那么求左孩子的Maximum
* 2:该节点没有左孩子,那么向上递归求(通过循环)一个存在右孩子的节点,即为所求节点的前驱节点
* @param data
* @return
*/
public Node Tree_Predecessor(int data)
{
Node x = Tree_Search(data); // 获得元素data 的引用
if(x==null) return null;
if(x.getLeft()!=null) // 第一种情况,存在左孩子
return Maximum(x.getLeft());
Node y = x.getParrent();
while(y!=null && y.getLeft()==x)
{
x=y;
y= y.getParrent();
}
return y;
}
/**
* funtion:删除树中的元素data(如果存在的话),删除时存在三种情况:
* 1:该节点没有孩子节点,则,直接删除
* 2:该节点有一个孩子节点,那么删除节点之后,将该节点的父节点执行该节点的子节点
* 3:存在两个子节点,那么将该节点的后继,覆盖带该节点即可,后继节点一定不会有两个子节点
* @param data
*/
public void Tree_Delete(int data)
{
Node z = Tree_Search(data);
Node x,y;
if(z==null)return; // 不存在元素data
if((z.getLeft()==null)||(z.getRight()==null)) //如果是前两种情况
{
y = z;
}
else y = Tree_Successor(data);// 第三种情况
if(y.getLeft()!=null) // 获得要删除节点的子节点
x = y.getLeft();
else x = y.getRight();
if(x!=null)
x.setParrent(y.getParrent());
if(y.getParrent()==null)
boot = x;
else if(y==y.getParrent().getLeft())
y.getParrent().setLeft(x);
else y.getParrent().setRight(x);
if(y!=z) //删除节点不是指定节点,那么是第三种情况
{
z.setData(y.getData()); //修改删除节点的data 域为它的后继节点的data域 ,相对于写该引用简单很多
}
}
}
MainClass ,调试的主类:
package SearchTree;
public class MainClass {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Tree T =new Tree();
int[] a = {4 ,3 ,5,2,6,7,1};
for(int i=0;i < a.length; i++)
{
T.Tree_Insert(new Node(null, null, null, a[i]));
}
T.InOrder_Tree_Walk();
System.out.println("The minmum element is :" +T.Tree_Minmum().getData());
System.out.println("The Maximum element is :" + T.Tree_Maximum().getData());
System.out.println("The element 6's successor is:" + T.Tree_Successor(6).getData());
System.out.println("The element 6's predecessor is:" + T.Tree_Predecessor(6).getData());
T.Tree_Delete(5);
T.InOrder_Tree_Walk();
}
}