/**
* 二叉查找树的节点不同:
* 含有一个key值,一个左右节点以及父节点。
**/
package DataStructure;
/**
* Copyright 2014 by Ruiqin Sun
* All right reserved
* created on 2014-9-9 下午5:05:13
**/
public class SearchTreeNode{
private int key;
private SearchTreeNode leftNode;
private SearchTreeNode rightNode;
private SearchTreeNode parent;
public SearchTreeNode(int key, SearchTreeNode leftNode, SearchTreeNode rightNode, SearchTreeNode parentNode){
this.key = key;
this.leftNode = leftNode;
this.rightNode = rightNode;
this.parent = parentNode;
}
/**
* @return the key
*/
public int getKey() {
return key;
}
/**
* @param key the key to set
*/
public void setKey(int key) {
this.key = key;
}
/**
* @return the leftNode
*/
public SearchTreeNode getLeftNode() {
return leftNode;
}
/**
* @param leftNode the leftNode to set
*/
public void setLeftNode(SearchTreeNode leftNode) {
this.leftNode = leftNode;
}
/**
* @return the rightNode
*/
public SearchTreeNode getRightNode() {
return rightNode;
}
/**
* @param rightNode the rightNode to set
*/
public void setRightNode(SearchTreeNode rightNode) {
this.rightNode = rightNode;
}
/**
* @return the parent
*/
public SearchTreeNode getParent() {
return parent;
}
/**
* @param parent the parent to set
*/
public void setParent(SearchTreeNode parent) {
this.parent = parent;
}
}
/**
* 二叉查找树
* 方便进行插入删除以及查找
**/
package DataStructure;
import java.util.ArrayList;
import java.util.List;
/**
* Copyright 2014 by Ruiqin Sun
* All right reserved
* created on 2014-9-9 下午8:18:07
**/
public class BinSearchTree {
private SearchTreeNode root = null;
// 遍历结点列表
private List<SearchTreeNode> nodelist = new ArrayList<SearchTreeNode>();
public boolean isEmpty(){
if(root == null){
return true;
}else{
return false;
}
}
/**
* 依据给定的关键字查找二叉树
* @param int key 给定关键字
* @return SearchTreeNode 匹配给定关键字的树结点
*/
public SearchTreeNode search(int key){
SearchTreeNode pNode = root;
while(pNode != null && pNode.getKey() != key){
if(key < pNode.getKey()){
pNode = pNode.getLeftNode();
}else{
pNode = pNode.getRightNode();
}
}//end while
return pNode;
}
/**
* 将给定的关键字插入到查找二叉树
* @param int key 给定关键字
* @return
*/
public void insert(int key){
SearchTreeNode parentNode = null;
// 首先必须县创建一个关键字为key的SearchTreeNode
SearchTreeNode newNode = new SearchTreeNode(key, null, null ,null);
SearchTreeNode pNode = root;
if(this.isEmpty()){
root = newNode;
return;
}else{
while(pNode != null){// 从根节点开始循环,将key放到合适的地方
parentNode = pNode;//首先将pNode值保持
if(key < pNode.getKey()){
pNode = pNode.getLeftNode();
}else if (key > pNode.getKey()){
pNode = pNode.getRightNode();
}else{
//当key值已存在时,直接返回
return;
}
}//end while
// System.out.println(parentNode.getKey());
if(key < parentNode.getKey()){//插入左树
parentNode.setLeftNode(newNode);
newNode.setParent(parentNode);
}else{
parentNode.setRightNode(newNode);
newNode.setParent(parentNode);
}
}
}
/**
*minElemNode: 在查询二叉树中查找关键字最小的树节点(左子树的最末尾的节点)
* @return 关键字最小的树节点
* throws Exception
*/
public SearchTreeNode minElemNode(SearchTreeNode node ) throws Exception{
if(node == null){
throw new Exception("树为空!");
}
while(node.getLeftNode() != null){
node = node.getLeftNode();
}
return node;
}
/**
*maxElemNode: 在查询二叉树中查找关键字最大的树节点(右子树的最末尾的节点)
* @return 关键字最大的树节点
* throws Exception
*/
public SearchTreeNode maxElemNode(SearchTreeNode node ) throws Exception{
if(node == null){
throw new Exception("树为空!");
}
while(node.getRightNode() != null){
node = node.getRightNode();
}
return node;
}
/**获取给定结点在中序遍历顺序下的后继结点
* @param SearchTreeNode node 给定树节点
* @return SearchTreeNode successor 若该结点存在中序遍历顺序下的后继结点,则返回其后继结点;否则返回 null
* throws Exception
*/
public SearchTreeNode successor(SearchTreeNode pNode) throws Exception{
if(pNode == null){
return null;
}
// 在查询二叉树中查找PNode右子树中关键字就小的树节点
while(pNode.getRightNode() != null){
return minElemNode(pNode.getRightNode());
}
// 若右子树为空,则pNode的后继节点是pnode的parent的parent(按照左-中-右的遍历顺序而得)
SearchTreeNode parent = pNode.getParent();
if(parent != null && pNode == parent.getRightNode()){
pNode = parent;
parent = parent.getParent();
}
return parent;
}
/**获取给定结点在中序遍历顺序下的前继结点
* @param SearchTreeNode node 给定树节点
* @return SearchTreeNode successor 若该结点存在中序遍历顺序下的后继结点,则返回其前继结点;否则返回 null
* throws Exception
*/
public SearchTreeNode preccessor(SearchTreeNode pNode) throws Exception{
if(pNode == null){
return null;
}
// 在查询二叉树中查找PNode左子树中关键字就大的树节点
while(pNode.getLeftNode() != null){
return maxElemNode(pNode.getLeftNode());
}
// 若左子树为空,则pNode的后继节点是pnode的parent的parent(按照左-中-右的遍历顺序而得)
SearchTreeNode parent = pNode.getParent();
if(parent != null && pNode == parent.getRightNode()){
pNode = parent;
parent = parent.getParent();
}
return parent;
}
/**
* 将给定的关键字从查找二叉树中删除
* @param int key 给定关键字
* 首先找到关键字为key的树节点pNode,然后判断:
* 如果pNode左子节点为空,右子节点不为空则,将右子节点与pNode的父节点相连
* 如果pNode左子节点不为空,右子节点为空则,将左子节点与pNode的父节点相连
* 如果pNode左子节点不为空,右子节点也不为空则,将PNode的后继结点删除,然后用后继结点代替此节点(后继结点的值赋给此节点即可)
* @return
*/
public void delete(int key) throws Exception{
// 首先找到一个关键字为key的SearchTreeNode
SearchTreeNode pNode =search(key);
if(pNode == null){
throw new Exception("树中不存在要删除的关键字!");
}
delete(pNode);
}
/**
* 将给定的关键字从查找二叉树中删除
* @param SearchTreeNode nodey 给定树节点
* 如果pNode左子节点为空,右子节点不为空则,将右子节点与pNode的父节点相连
* 如果pNode左子节点不为空,右子节点为空则,将左子节点与pNode的父节点相连
* 如果pNode左子节点不为空,右子节点也不为空则,将PNode的后继结点删除,然后用后继结点代替此节点(后继结点的值赋给此节点即可)
* @return
*/
public void delete(SearchTreeNode node) throws Exception{
// 如果node为空直接返回
if(node == null){
return;
}
// 当左子节点为空,右子节点空,直接删除,判断node是parent的左/右位置,将对应的位置设为null
if(node.getLeftNode() == null && node.getRightNode() == null){
SearchTreeNode parent = node.getParent();
if(node == parent.getLeftNode()){
parent.setLeftNode(null);
}else{
parent.setRightNode(null);
}
return; //必须跳出此函数,结束删除
}
// 当左子节点为非空,右子节点空,直接删除,判断node是parent的左/右位置,将左子节点代替node(需要双向设置)
if(node.getLeftNode() != null && node.getRightNode() == null){
SearchTreeNode parent = node.getParent();
if(node == parent.getLeftNode()){
parent.setLeftNode(node.getLeftNode());
node.getLeftNode().setParent(parent) ;
}else{
parent.setRightNode(node.getLeftNode());
node.getLeftNode().setParent(parent) ;
}
return; //必须跳出此函数,结束删除
}
// 当左子节点为空,右子节点非空,直接删除,判断node是parent的左/右位置,将右子节点代替node(需要双向设置)
if(node.getLeftNode() == null && node.getRightNode() != null){
SearchTreeNode parent = node.getParent();
if(node == parent.getLeftNode()){
parent.setLeftNode(node.getRightNode());
node.getRightNode().setParent(parent) ;
}else{
parent.setRightNode(node.getRightNode());
node.getRightNode().setParent(parent) ;
// delete(node.getRightNode());
// node.setKey(node.getRightNode().getKey());
}
return; //必须跳出此函数,结束删除
}
// 当左子节点、右子节点都非空,则删除该结点的后继结点,并用该后继结点取代该结点
if(node.getLeftNode() != null && node.getRightNode() != null){
SearchTreeNode successor =successor(node);
delete(successor);
node.setKey(successor.getKey());
}
}
/*
*前序遍历二叉树
* */
public void preOrder(SearchTreeNode node){
if(node != null){
System.out.print(node.getKey());
preOrder(node.getLeftNode());
preOrder(node.getRightNode());
}
}
/*
*中序遍历二叉树
* */
public void inOrder(SearchTreeNode node){
if(node != null){
inOrder(node.getLeftNode());
System.out.print(node.getKey());
inOrder(node.getRightNode());
}
}
/*
*后序遍历二叉树
* */
public void postOrder(SearchTreeNode node){
if(node != null){
postOrder(node.getLeftNode());
postOrder(node.getRightNode());
System.out.print(node.getKey());
}
}
/**中序遍历二叉树 获得树节点的列表
* @params
* @return
*/
private List<SearchTreeNode> inOderList() {
// TODO Auto-generated method stub
if(nodelist !=null){//首先清空节点雷彪,重新获取
nodelist.clear();
}
inOderList(root);
return nodelist;
}
/**
* inOrderTraverse: 对给定二叉查找树进行中序遍历
*
* @param root
* 给定二叉查找树的根结点
*/
private void inOderList(SearchTreeNode root) {
// TODO Auto-generated method stub
if(root != null){
inOderList(root.getLeftNode());
nodelist.add(root);
inOderList(root.getRightNode());
}
}
/**
* toStringOfOrderList: 获取二叉查找树中关键字的有序列表
*
* @return 二叉查找树中关键字的有序列表
*/
public String toStringOfOrderList() {
StringBuilder sbuilder = new StringBuilder("[");
for(SearchTreeNode node : inOderList()){
sbuilder.append(node.getKey());
sbuilder.append(" ");
}
sbuilder.append("]");
// System.out.println(sbuilder.toString());
return sbuilder.toString();
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
try{
BinSearchTree bst = new BinSearchTree();
System.out.println("查找树是否为空? " + (bst.isEmpty() ? "是" : "否"));
int[] keys = new int[] { 15, 6, 18, 3, 7, 13, 20, 2, 9, 4 };
for(int key :keys ){
System.out.println("insert " +key);
bst.insert(key);
}
System.out.println("中序遍历: " );
bst.inOrder(bst.root);
System.out.println(" " );
System.out.println("转化为String: "+bst.toStringOfOrderList() );
SearchTreeNode maxKeyNode = bst.maxElemNode(bst.root);
System.out.println("最大关键字: " + maxKeyNode.getKey());
// System.out.println("删除key=18的树节点(只有右子树):" );
// bst.delete(18);
// System.out.println("删除key=18的树节点后的bst转化为String: "+bst.toStringOfOrderList() );
// System.out.println("删除key=13的树节点(只有左子树) :" );
// bst.delete(13);
// System.out.println("删除key=13的树节点后的bst转化为String: "+bst.toStringOfOrderList() );
System.out.println("删除key=3的树节点(有左子树和右子树) :" );
bst.delete(3);
System.out.println("删除key=3的树节点后的bst转化为String: "+bst.toStringOfOrderList() );
System.out.println("中序遍历: " );
bst.inOrder(bst.root);
}catch(Exception e){
System.out.println(e.getMessage());
e.printStackTrace();
}
}
}