/***@authorshuqin1984 2011-3-13
*
* 此程序实现一个二叉查找树的功能,可以进行动态插入、删除关键字;
* 查询给定关键字、最小关键字、最大关键字;转换为有序列表(用于排序)
*
**/
packagedatastructure.tree;importjava.util.ArrayList;importjava.util.List;public classBinarySearchTree {//树的根结点
private TreeNode root = null;//遍历结点列表
private List nodelist = new ArrayList();private classTreeNode {private intkey;privateTreeNode leftChild;privateTreeNode rightChild;privateTreeNode parent;public TreeNode(intkey, TreeNode leftChild, TreeNode rightChild, TreeNode parent) {this.key =key;this.leftChild =leftChild;this.rightChild =rightChild;this.parent =parent;
}public intgetKey() {returnkey;
}publicString toString()
{
String leftkey= (leftChild == null ? "": String.valueOf(leftChild.key));
String rightkey= (rightChild == null ? "": String.valueOf(rightChild.key));return "(" + leftkey + " , " + key + " , " + rightkey + ")";
}
}/*** isEmpty: 判断二叉查找树是否为空;若为空,返回 true ,否则返回 false .
**/
public booleanisEmpty()
{if (root == null) {return true;
}else{return false;
}
}/*** TreeEmpty: 对于某些二叉查找树操作(比如删除关键字)来说,若树为空,则抛出异常。*/
public void TreeEmpty() throwsException
{if(isEmpty()) {throw new Exception("树为空!");
}
}/*** search: 在二叉查找树中查询给定关键字
*@paramkey 给定关键字
*@return匹配给定关键字的树结点*/
public TreeNode search(intkey)
{
TreeNode pNode=root;while (pNode != null && pNode.key !=key) {if (key
pNode=pNode.leftChild;
}else{
pNode=pNode.rightChild;
}
}returnpNode;
}/*** minElemNode: 获取二叉查找树中的最小关键字结点
*@return二叉查找树的最小关键字结点
*@throwsException 若树为空,则抛出异常*/
public TreeNode minElemNode(TreeNode node) throwsException
{if (node == null) {throw new Exception("树为空!");
}
TreeNode pNode=node;while (pNode.leftChild != null) {
pNode=pNode.leftChild;
}returnpNode;
}/*** maxElemNode: 获取二叉查找树中的最大关键字结点
*@return二叉查找树的最大关键字结点
*@throwsException 若树为空,则抛出异常*/
public TreeNode maxElemNode(TreeNode node) throwsException
{if (node == null) {throw new Exception("树为空!");
}
TreeNode pNode=node;while (pNode.rightChild != null) {
pNode=pNode.rightChild;
}returnpNode;
}/*** successor: 获取给定结点在中序遍历顺序下的后继结点
*@paramnode 给定树中的结点
*@return若该结点存在中序遍历顺序下的后继结点,则返回其后继结点;否则返回 null
*@throwsException*/
public TreeNode successor(TreeNode node) throwsException
{if (node == null) {return null;
}//若该结点的右子树不为空,则其后继结点就是右子树中的最小关键字结点
if (node.rightChild != null) {returnminElemNode(node.rightChild);
}//若该结点右子树为空
TreeNode parentNode =node.parent;while (parentNode != null && node ==parentNode.rightChild) {
node=parentNode;
parentNode=parentNode.parent;
}returnparentNode;
}/*** precessor: 获取给定结点在中序遍历顺序下的前趋结点
*@paramnode 给定树中的结点
*@return若该结点存在中序遍历顺序下的前趋结点,则返回其前趋结点;否则返回 null
*@throwsException*/
public TreeNode precessor(TreeNode node) throwsException
{if (node == null) {return null;
}//若该结点的左子树不为空,则其前趋结点就是左子树中的最大关键字结点
if (node.leftChild != null) {returnmaxElemNode(node.leftChild);
}//若该结点左子树为空
TreeNode parentNode =node.parent;while (parentNode != null && node ==parentNode.leftChild) {
node=parentNode;
parentNode=parentNode.parent;
}returnparentNode;
}/*** insert: 将给定关键字插入到二叉查找树中
*@paramkey 给定关键字*/
public void insert(intkey)
{
TreeNode parentNode= null;
TreeNode newNode= new TreeNode(key, null, null,null);
TreeNode pNode=root;if (root == null) {
root=newNode;return;
}while (pNode != null) {
parentNode=pNode;if (key
pNode=pNode.leftChild;
}else if (key >pNode.key) {
pNode=pNode.rightChild;
}else{//树中已存在匹配给定关键字的结点,则什么都不做直接返回
return;
}
}if (key
parentNode.leftChild=newNode;
newNode.parent=parentNode;
}else{
parentNode.rightChild=newNode;
newNode.parent=parentNode;
}
}/*** insert: 从二叉查找树中删除匹配给定关键字相应的树结点
*@paramkey 给定关键字*/
public void delete(int key) throwsException
{
TreeNode pNode=search(key);if (pNode == null) {throw new Exception("树中不存在要删除的关键字!");
}
delete(pNode);
}/*** delete: 从二叉查找树中删除给定的结点.
*@parampNode 要删除的结点
*
* 前置条件: 给定结点在二叉查找树中已经存在
*@throwsException*/
private void delete(TreeNode pNode) throwsException
{if (pNode == null) {return;
}if (pNode.leftChild == null && pNode.rightChild == null) { //该结点既无左孩子结点,也无右孩子结点
TreeNode parentNode =pNode.parent;if (pNode ==parentNode.leftChild) {
parentNode.leftChild= null;
}else{
parentNode.rightChild= null;
}return;
}if (pNode.leftChild == null && pNode.rightChild != null) { //该结点左孩子结点为空,右孩子结点非空
TreeNode parentNode =pNode.parent;if (pNode ==parentNode.leftChild) {
parentNode.leftChild=pNode.rightChild;
pNode.rightChild.parent=parentNode;
}else{
parentNode.rightChild=pNode.rightChild;
pNode.rightChild.parent=parentNode;
}return;
}if (pNode.leftChild != null && pNode.rightChild == null) { //该结点左孩子结点非空,右孩子结点为空
TreeNode parentNode =pNode.parent;if (pNode ==parentNode.leftChild) {
parentNode.leftChild=pNode.leftChild;
pNode.rightChild.parent=parentNode;
}else{
parentNode.rightChild=pNode.leftChild;
pNode.rightChild.parent=parentNode;
}return;
}//该结点左右孩子结点均非空,则删除该结点的后继结点,并用该后继结点取代该结点
TreeNode successorNode =successor(pNode);
delete(successorNode);
pNode.key=successorNode.key;
}/*** inOrderTraverseList: 获得二叉查找树的中序遍历结点列表
*@return二叉查找树的中序遍历结点列表*/
public ListinOrderTraverseList()
{if (nodelist != null) {
nodelist.clear();
}
inOrderTraverse(root);returnnodelist;
}/*** inOrderTraverse: 对给定二叉查找树进行中序遍历
*@paramroot 给定二叉查找树的根结点*/
private voidinOrderTraverse(TreeNode root)
{if (root != null) {
inOrderTraverse(root.leftChild);
nodelist.add(root);
inOrderTraverse(root.rightChild);
}
}/*** toStringOfOrderList: 获取二叉查找树中关键字的有序列表
*@return二叉查找树中关键字的有序列表*/
publicString toStringOfOrderList()
{
StringBuilder sbBuilder= new StringBuilder(" [ ");for(TreeNode p: inOrderTraverseList()) {
sbBuilder.append(p.key);
sbBuilder.append(" ");
}
sbBuilder.append("]");returnsbBuilder.toString();
}/*** 获取该二叉查找树的字符串表示*/
publicString toString()
{
StringBuilder sbBuilder= new StringBuilder(" [ ");for(TreeNode p: inOrderTraverseList()) {
sbBuilder.append(p);
sbBuilder.append(" ");
}
sbBuilder.append("]");returnsbBuilder.toString();
}publicTreeNode getRoot() {returnroot;
}public static void testNode(BinarySearchTree bst, TreeNode pNode) throwsException {
System.out.println("本结点: " +pNode);
System.out.println("前趋结点: " +bst.precessor(pNode));
System.out.println("后继结点: " +bst.successor(pNode));
}public static voidtestTraverse(BinarySearchTree bst) {
System.out.println("二叉树遍历:" +bst);
System.out.println("二叉查找树转换为有序列表: " +bst.toStringOfOrderList());
}public static voidmain(String[] args)
{try{
BinarySearchTree bst= newBinarySearchTree();
System.out.println("查找树是否为空? " + (bst.isEmpty() ? "是" : "否"));int[] keys = new int[] {15, 6, 18, 3, 7, 13, 20, 2, 9, 4};for (intkey: keys) {
bst.insert(key);
}
System.out.println("查找树是否为空? " + (bst.isEmpty() ? "是" : "否"));
TreeNode minkeyNode=bst.minElemNode(bst.getRoot());
System.out.println("最小关键字: " +minkeyNode.getKey());
testNode(bst, minkeyNode);
TreeNode maxKeyNode=bst.maxElemNode(bst.getRoot());
System.out.println("最大关键字: " +maxKeyNode.getKey());
testNode(bst, maxKeyNode);
System.out.println("根结点关键字: " +bst.getRoot().getKey());
testNode(bst, bst.getRoot());
testTraverse(bst);
System.out.println("****************************** ");
System.out.println("查找 7 : " + (bst.search(7) != null ? "查找成功!" : "查找失败,不存在该关键字!"));
bst.delete(7);
System.out.println("查找 7 : " + (bst.search(7) != null ? "查找成功!" : "查找失败,不存在该关键字!"));
System.out.println("查找 12 : " + (bst.search(12) != null ? "查找成功!" : "查找失败,不存在该关键字!"));
bst.insert(12);
System.out.println("查找 12 : " + (bst.search(12) != null ? "查找成功!" : "查找失败,不存在该关键字!"));
testTraverse(bst);
System.out.println("****************************** ");
bst.insert(16);
bst.delete(6);
bst.delete(4);
testTraverse(bst);
}catch(Exception e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
}
}