BST:
主要的是 search、insert、delete三个操作,理想的效率 都是O (logN)
delete比较复杂,有三种情况:
1,被删除的结点没有孩子
直接删除
2,有一个孩子
把sub tree 连接到 删除结点的 父节点上
3,有两个孩子
思路是:把此问题化为 问题2(只有一个孩子)
找到删除结点 的 中序前趋结点/中序后继结点,然后用找到的结点替换删除结点。
然后,删除 找到的前趋/后继 结点(必然只有一个孩子)。
详细的看代码:
Notes:
用到了 前几天写的 BinaryTree类,算是组合吧
Console的测试结果:
0 4 7 11 14 19 21 22 29 31 35 39 43 46 48 50 54 59 61 65 69 79 83 86 87 89 91 93 95 97
Test 1:
Got 21
After the delete: 0 4 7 11 14 19 22 29 31 35 39 43 46 48 50 54 59 61 65 69 79 83 86 87 89 91 93 95 97
Test 2:
Ain't got 44
Test 3:
Got 4
After the delete: 0 7 11 14 19 22 29 31 35 39 43 46 48 50 54 59 61 65 69 79 83 86 87 89 91 93 95 97
Test 4:
Ain't got 73
Test 5:
Ain't got 3
/**
* Build a BST based on BinaryTree
* Operations: insert , search, delete
* @author Jason
*
*/
public class BinarySearchTree<T extends Comparable<T>> {
public BinaryTree<T> tree;
public BinarySearchTree()
{
tree=new BinaryTree<T>();
}
public void insert(T item)
{
BinaryTree<T> root=tree.findRoot();
BinaryTree<T> newNode=new BinaryTree<T>(item);
// empty tree
if(root.getData()==null)
{
root.setData(item);
return ;
}
int c;
boolean flag=true;
while(flag)
{
c=item.compareTo((T)root.getData());
if(c>0) // right
{
if(root.rightChild==null)
{
flag=false;
root.rightChild=newNode;
newNode.parent=root;
}
else root=root.rightChild;
}
else if(c<0) //left
{
if(root.leftChild==null)
{
flag=false;
root.leftChild=newNode;
newNode.parent=root;
}
else root=root.leftChild;
}
else // got it and ignore
flag=false;
}
}
public BinaryTree<T> search(T key)
{
BinaryTree<T> root=tree.findRoot();
// empty tree
if(root.getData()==null)
return null;
int c;
boolean flag=true;
while(flag)
{
c=key.compareTo((T)root.getData());
if(c>0) // right
{
if(root.rightChild==null)
flag=false;
else root=root.rightChild;
}
else if(c<0) //left
{
if(root.leftChild==null)
flag=false;
else root=root.leftChild;
}
else // got it and return it;
return root;
}
return null;
}
public T delete(T key)
{
// not found
BinaryTree<T> node=search(key);
if(node==null) return null;
BinaryTree<T> temp;
// no child
if(node.rightChild==null && node.leftChild==null)
{
deleteHere(node,null);
return node.getData();
}
// two children, replace node with the preceding-inorder-node, then delete p-i-n
if(node.rightChild!=null && node.leftChild!=null)
{
// replace
temp=findPre(node);
node.setData( temp.getData() );
node=temp;
}
// one child, set temp to be the sub-tree which is needed to attach
if(node.rightChild!=null)
temp=node.rightChild;
else
temp=node.leftChild;
deleteHere(node,temp);
return node.getData();
}
// for deleteNode which has one child
public void deleteHere(BinaryTree<T> node, BinaryTree<T> subTree)
{
BinaryTree<T> parent=node.parent;
if(node==parent.leftChild)
parent.leftChild=subTree;
else
parent.rightChild=subTree;
}
// find the preceding-inorder-node
public BinaryTree<T> findPre(BinaryTree<T> node)
{
BinaryTree<T> pre=node.leftChild;
while(pre.rightChild!=null)
pre=pre.rightChild;
return pre;
}
public static void main(String [] args)
{
BinarySearchTree<Integer> bst=new BinarySearchTree<Integer>();
for(int i=0; i<40 ;i ++)
{
int temp=(int)(Math.random()*100);
bst.insert(temp);
}
bst.tree.travellRecursive( bst.tree.findRoot() );
for(int test=1 ; test<=5; test++)
{
System.out.println("\nTest "+test+":");
int temp=(int)(Math.random()*100);
if(bst.search(temp)!=null)
{
System.out.println("Got "+temp);
bst.delete(temp);
System.out.print("After the delete: ");
bst.tree.travellRecursive( bst.tree.findRoot() );
}
else
System.out.println("Ain't got "+temp);
}
}
}