1 二叉排序树
1.1二叉排序树又称二叉查找树。
根节点的左子树一定小于根节点中的value值而下于右子树中的value。
二叉排序树:或者是一棵空树,或者是具有下列性质的二叉树:
若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
它的左、右子树也分别为二叉排序树。
1.2 尝试写类似TreeMap的集合;
每条映射的结构为
static final class Entry<V, K> implements Map.Entry<K, V> {
/**
* 存储的key值
*/
private K key;
/**
* 存储的value值
*/
private V value;
/**
* 指向左子数
*/
private Entry<K, V> left = null;
/**
* 指向右子数
*/
private Entry<K, V> right = null;
/**
* 指向父节点
*/
private Entry<V, K> parentRoot = null;
public Entry(K key, V value, Entry<V, K> parentRoot) {
this.key = key;
this.value = value;
this.parentRoot = parentRoot;
}
继承Map中的Entry集合
核心代码:
插入函数
/**
* 将数据插入到树的指定位置
* 说明:记录父节点,通过他的左右节点,如果节点为空,value值满足二叉排序树的特征,
* 则插入,否则递归查找适合的位置
* @param parentRoot
* 父节点
* @param key
* 待插入节点key值
* @param value
* 待插入节点value值
*/
public void insertIntoTree(Entry<Integer, Integer> parentRoot, Integer key,
Integer value) {
if (parentRoot != null) {
if (parentRoot.getKey() > key) {// 左节点
if (parentRoot.left == null) {// 左节点可进行插入
parentRoot.left = new Entry<Integer, Integer>(key, value,
parentRoot);
} else {// 向左节点下搜索可插入的节点
insertIntoTree(parentRoot.left, key, value);
}
} else if (parentRoot.getKey() < key) {// 右节点
if (parentRoot.right == null) {// 右节点可插入
parentRoot.right = new Entry<Integer, Integer>(key, value,
parentRoot);
} else {// 向右节点下搜索可插入的节点
insertIntoTree(parentRoot.right, key, value);
}
} else {// 当出现重复的key值重置value值
parentRoot.setValue(value);
}
} else {
// 生成最高根节点
this.root = new Entry<Integer, Integer>(key, value, null);
}
}
根据key值查找节点:
/**
* 根据key查找对应的节点 当前树无节点时,返回null
*
* @param root
* 根节点,传入的根节点是相对的
* @param key
* 要查找的节点的key值
* @return 节点
*/
public Entry<Integer, Integer> getEntry(Entry<Integer, Integer> root,
Integer key) {
if (root == null) {// 当前所在的节点为空,
return null;
} else {
if (root.getKey() > key) {// 当前节点的key值大于key,向左递归
return getEntry(root.left, key);
} else if (root.getKey() == key) {// 当前节点即为要查找的节点
return root;
} else {// 当前节点的key值小于key,向右递归查找
return getEntry(root.right, key);
}
}
}
删除节点:
/**
* 删除指定的映射
*
* @param key
* 键值对的key
*/
public void remove(Integer key) {
Entry entry = get(key);//要删除的节点
Entry entryPar = getParentEntry(this.root, key);//要删除的节点的父节点
if ((entry.left == null) && (entry.right == null)) {// 删除的节点为叶子节点
// 判断该叶子节点为父节点的左节点还是右节点
if (entryPar.left == entry) {
// 删除的节点为左节点
// 将父节点指向左节点的指针指为null
entryPar.left = null;
} else if (entryPar.right == entry) {
// 删除的节点为右节点
// 将父节点指向右节点的指针指为null
entryPar.right = null;
} else {
}
} else if (entry.left != null && entry.right == null) {// 删除的节点只有左节点
entryPar.left = entry.left;
} else if (entry.left == null && entry.right != null) {// 删除的节点只有右节点
entryPar.right = entry.right;
} else {// 左右节点均不为空
// 在该节点的右节点中找到value最小的节点,即为右节点中最左边的位置
Entry<Integer, Integer> minEntry = entry.right;// 最小value值的节点
Entry<Integer, Integer> minEntryPar = minEntry;// 最小value值的节点父节点
while (minEntry.left != null) {
minEntryPar = minEntry;
minEntry = minEntry.left;
}
entry.value = minEntry.value;// 替换值
if (minEntry == minEntryPar) {// 特殊情况,被删节点的右节点即是最小value值的节点,
//即最小的节点没有左节点,只有右节点,并且它的父节点也没有左节点,三个在一条直线上
entryPar.right = minEntry.right;
} else {// 一般情况,最小节点只有右节点。没有左节点,直接嫁接
minEntryPar.left = minEntry.right;
}
}
}
未完待续。。。