标签:tty order mil ash imu 速度 时间复杂度 round 微软
/**
* 节点类
*
* @author Frank
*
*/
public class TreeNode {
int keyData;// 关键值(可能还有别的非关键数据,这里省略)
TreeNode leftChild;// 左子节点
TreeNode rightChild;// 右子节点
public TreeNode(int keyData) {
super();
this.keyData = keyData;
}
/**
* 显示该节点信息
*/
public void display() {
System.out.println(
"TreeNode [keyData=" + keyData + ", leftChild=" + leftChild + ", rightChild=" + rightChild + "]");
}
@Override
public String toString() {
return "TreeNode [keyData=" + keyData + "]";
}
}
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
/**
* 二叉查找树
*
* @author Frank
*
*/
public class Tree {
TreeNode root;// 根节点
private TreeNode parent;// 父节点
public Tree(TreeNode root) {
super();
this.root = root;
}
/**
* 以关键值查找节点是否存在
*
* @param keyData
* 节点关键值
* @return 若该树包含关键值对应的 Node,返回 true
*/
public boolean findNode(int keyData) {
TreeNode current = root;// 当前节点
while (current != null) {
if (current.keyData == keyData)
return true;// 找到了
if (current.keyData > keyData) // 往左遍历
current = current.leftChild;
if (current.keyData < keyData) // 往右遍历
current = current.rightChild;
}
return false;// 未找到
}
/**
* 将节点插入当前树
*
* @param node
* 新插入的节点
*/
public void insert(TreeNode node) {
if (!this.isEmpty()) {
boolean isLeftChild = true;
int keyData = node.keyData;
TreeNode current = root;// 当前节点
parent = null;
while (current != null) {
parent = current;
if (keyData == current.keyData)
return;// 关键值一样则不插入
current = (keyData < current.keyData) ? (current.leftChild) : (current.rightChild);
isLeftChild = (keyData < parent.keyData) ? true : false;
}
if (isLeftChild) {
parent.leftChild = node;
} else {
parent.rightChild = node;
}
}
}
/**
* 将集合中的所有节点插入当前树
*
* @param node
* 新插入的节点
*/
public void insert(Set<TreeNode> nodeSet) {
Iterator<TreeNode> iterator = nodeSet.iterator();
while (iterator.hasNext()) {
insert(iterator.next());
}
}
/**
* 判断当前树是否为空
*
* @return 若为空,返回 true
*/
public boolean isEmpty() {
return root == null;
}
// 通过递归实现中序遍历输出
private void getOrder(TreeNode localRoot) {
if (localRoot != null) {
getOrder(localRoot.leftChild);
System.out.print(localRoot.keyData + " ");
getOrder(localRoot.rightChild);
}
}
/**
* 中序遍历指定的子树,若指定的节点并不是本树的节点(以关键值为标准,可能出现非关键值不一样的正常遍历),则不输出任何值
*
* @param localRoot
* 指定节点对象,若为 root 节点则遍历当前树
*/
public void inOrder(TreeNode localRoot) {
if (localRoot != null && findNode(localRoot.keyData)) {
TreeNode current = getNode(localRoot.keyData);
getOrder(current);
System.out.println();
}
}
/**
* 获取指定关键值对应的节点,该节点需存在于本树中
*
* @param keyData
* 节点关键值
* @return 若存在这样的节点则返回此节点,否则返回 null
*/
public TreeNode getNode(int keyData) {
TreeNode current = root;// 当前节点
while (current != null) {
if (current.keyData == keyData)
return current;// 找到了
if (current.keyData > keyData) // 往左遍历
current = current.leftChild;
if (current.keyData < keyData) // 往右遍历
current = current.rightChild;
}
return null;// 未找到
}
/**
* 获取当前树的最小关键值节点
*
* @return 最小关键值对应的节点,若树为空则返回 null
*/
public TreeNode minimum() {
if (!this.isEmpty()) {
parent = null;
TreeNode minmum = root;
while ((minmum = minmum.leftChild) != null) {
parent = minmum;
}
return parent;
}
return null;
}
/**
* 获取当前树的最大关键值节点
*
* @return 最大关键值对应的节点,若树为空则返回 null
*/
public TreeNode maximum() {
if (!this.isEmpty()) {
parent = null;
TreeNode maximum = root;
while ((maximum = maximum.rightChild) != null) {
parent = maximum;
}
return parent;
}
return null;
}
/**
* 获取指定节点的子节点个数
*
* @param keyData
* 节点关键值
* @return 返回拥有 keyData 关键值的节点的子节点个数,若节点不存在与本树,返回-1
*/
public HashMap<Integer, Boolean> numOfChildren(int keyData) {
HashMap<Integer, Boolean> returnMap = new HashMap<Integer, Boolean>();
if (this.isEmpty() || !findNode(keyData)) {
returnMap.put(-1, false);
return returnMap;
}
TreeNode current = root;
parent = null;
boolean isLeftChild = true;
while (current != null) {
if (keyData == current.keyData) {
break;
}
parent = current;
current = (keyData < current.keyData) ? (current.leftChild) : (current.rightChild);
isLeftChild = (keyData < parent.keyData) ? true : false;
}
if (current.leftChild == null && current.rightChild == null) {
returnMap.put(0, isLeftChild);
} else if (current.leftChild != null && current.rightChild != null) {
returnMap.put(2, isLeftChild);
} else {
returnMap.put(1, isLeftChild);
}
return returnMap;
}
/**
* 删除指定关键值对应的节点,若为非叶子节点,当直接子节点仅有一个时,由该子节点继承,若直接子节点为两个,则由后继节点继承,各子节点保持规律不变,
* 即左子节点小于父节点,父节点小于右子节点
*
* @param keyData
* 叶子节点的关键值
* @return 删除成功返回 true,否则返回 false
*/
public boolean delete(int keyData) {
HashMap<Integer, Boolean> map = numOfChildren(keyData);
boolean isLeftChild = map.values().iterator().next();
switch (map.keySet().iterator().next()) {
case -1:
return false;
case 0:
if (isLeftChild) {
parent.leftChild = null;
} else {
parent.rightChild = null;
}
return true;
case 1:
if (isLeftChild) {
TreeNode current = parent.leftChild;
parent.leftChild = (current.leftChild == null) ? current.rightChild : parent.leftChild.leftChild;
} else {
TreeNode current = parent.rightChild;
parent.rightChild = (current.leftChild == null) ? current.rightChild : parent.leftChild.leftChild;
}
return true;
case 2:
TreeNode successorNode = getSuccessor(new TreeNode(keyData));// 该节点的后继节点,即将替换被删除节点
TreeNode delNode = null;// 将要删除的节点
if (isLeftChild) {// 将要删除的节点是其父节点的左子节点
if (parent == null) {// 删除整个树
root = null;
return true;
}
delNode = parent.leftChild;
if (delNode.rightChild == null) {
break;
} else if (successorNode.keyData == delNode.rightChild.keyData) {// 后继节点是delNode的右子节点
parent.leftChild = successorNode;// 1.将要删除的节点替换为后继节点
successorNode.leftChild = delNode.leftChild;// 2.将后继节点的左子节点替换为将要删除的节点的左子节点
} else {// 后继节点是delNode的右子节点的左后代
TreeNode successorParent = getParent(successorNode);// 获取后继节点的父节点,后继节点一定是这个父节点的左子节点
parent = getParent(delNode);
successorParent.leftChild = successorNode.rightChild;// 1.将后继节点的父节点的左子节点替换为后继节点的右子节点
successorNode.rightChild = delNode.rightChild;// 2.将后继节点的右子节点换为将要删除的节点的右子节点
parent.leftChild = successorNode;// 3.将要删除的节点替换为后继节点
successorNode.leftChild = delNode.leftChild;// 4.将后继节点的左子节点替换为将要删除的节点的左子节点
}
} else {// 将要删除的节点是其父节点的右子节点
delNode = parent.rightChild;
if (successorNode.keyData == delNode.rightChild.keyData) {// 后继节点是delNode的右子节点
parent.rightChild = successorNode;// 1.将要删除的节点替换为后继节点
successorNode.leftChild = delNode.leftChild;// 2.将后继节点的左子节点替换为将要删除的节点的左子节点
} else {// 后继节点是delNode的右子节点的左后代
TreeNode successorParent = getParent(successorNode);// 获取后继节点的父节点,后继节点一定是这个父节点的左子节点
parent = getParent(delNode);
successorParent.leftChild = successorNode.rightChild;// 1.将后继节点的父节点的左子节点替换为后继节点的右子节点
successorNode.rightChild = delNode.rightChild;// 2.将后继节点的右子节点换为将要删除的节点的右子节点
parent.rightChild = successorNode;// 3.将要删除的节点替换为后继节点
successorNode.leftChild = delNode.leftChild;// 4.将后继节点的左子节点替换为将要删除的节点的左子节点
}
}
return true;
}
return false;
}
// 获取指定节点的父节点
private TreeNode getParent(TreeNode node) {
int keyData = node.keyData;
if (this.isEmpty() || !findNode(keyData)) {
return null;
}
TreeNode current = root;
parent = null;
while (current != null) {
if (keyData == current.keyData) {
break;
}
parent = current;
current = (keyData < current.keyData) ? (current.leftChild) : (current.rightChild);
}
return parent;
}
/**
* 获取指定节点的后继节点,后继节点应为:在该节点的子节点中,关键值大于该节点关键值且最接近的那个,该方法为删除方法提供支持
*
* @param del
* 将要删除的节点
* @return
*/
private TreeNode getSuccessor(TreeNode del) {
if (this.isEmpty() || !findNode(del.keyData))
return null;
int keyData = del.keyData;
TreeNode current = root;
while (current != null) {
if (keyData == current.keyData) {
break;
}
current = (keyData < current.keyData) ? (current.leftChild) : (current.rightChild);
}
if (current.rightChild == null) {
return null;// 无后继节点
}
TreeNode successorNode = current.rightChild;
while (successorNode.leftChild != null) {
successorNode = successorNode.leftChild;
}
return successorNode;
}
}
标签:tty order mil ash imu 速度 时间复杂度 round 微软
原文地址:http://www.cnblogs.com/chendifan/p/6883660.html