二叉搜索树
一,概念
树节点增加key属性,用来比较大小,key不能重复
对于任意树节点,他的key比左子树大,比右子树小
1.前驱
比当前节点的key小的节点中,key最大的节点
左子树key最大的节点 或者 最后一个自左而来的节点
2.后继
比当前节点的key大的节点中,key最小的节点
右子树key最小的节点 或者 最后一个自右而来的节点
二,方法
注:节点类在最后实现代码中给出,由于导入原因,
缩进有所不同,可放入idea中一键格式化
1.put方法
不断根据key寻找插入位置,并通过prev记录上一个节点,
key存在则更新value,不存在则判断key与prev的key决定插入位置
public void put(KeyType key, ValueType value) {
BSTNode<KeyType, ValueType> p = root;
BSTNode<KeyType, ValueType> prev = null;
while (p != null) {
prev = p;
int result = key.compareTo(p.key);
if (result < 0) {
p = p.left;
} else if (result > 0) {
p = p.right;
} else {
p.value = value;
return;
}
}
if (prev == null) {
root = new BSTNode<KeyType, ValueType>(key, value);
return;
}
if (key.compareTo(prev.key) < 0) {
prev.left = new BSTNode<KeyType, ValueType>(key, value);
} else {
prev.right = new BSTNode<KeyType, ValueType>(key, value);
}
}
2.get方法
不断根据key寻找节点,找到返回对应的value,不存在返回null
public ValueType get(KeyType key) {
BSTNode<KeyType, ValueType> p = root;
while (p != null) {
int result = key.compareTo(p.key);
if (result < 0) {
p = p.left;
} else if (result > 0) {
p = p.right;
} else {
return p.value;
}
}
return null;
}
3.寻找前驱
根据key寻找对应节点,并在每一次进入右子树之前记录当前节点为prev
左子树存在则前驱为左子树的最大值,否则为prev
public ValueType findPrecursor(KeyType key) {
BSTNode<KeyType, ValueType> precursor = findPrecursor(root, key);
return precursor != null ? precursor.value : null;
}
private BSTNode<KeyType, ValueType> findPrecursor(BSTNode<KeyType, ValueType> node, KeyType key) {
BSTNode<KeyType, ValueType> p = node;
BSTNode<KeyType, ValueType> pre = null;
while (p != null) {
if (key.compareTo(p.key) < 0) {
p = p.left;
} else if (key.compareTo(p.key) > 0) {
pre = p;
p = p.right;
} else {
break;
}
}
if (p == null) {
return null;
}
if (p.left == null) {
return pre;
}
return max(p.left);
}
4.寻找后继
根据key寻找对应节点,并在每一次进入左子树之前记录当前节点为prev
右子树存在则前驱为右子树的最小值,否则为prev
public ValueType findSubsequent(KeyType key) {
BSTNode<KeyType, ValueType> subsequent = findSubsequent(root, key);
return subsequent != null ? subsequent.value : null;
}
private BSTNode<KeyType, ValueType> findSubsequent(BSTNode<KeyType, ValueType> node, KeyType key) {
BSTNode<KeyType, ValueType> p = node;
BSTNode<KeyType, ValueType> pre = null;
while (p != null) {
if (key.compareTo(p.key) < 0) {
pre = p;
p = p.left;
} else if (key.compareTo(p.key) > 0) {
p = p.right;
} else {
break;
}
}
if (p == null) {
return null;
}
if (p.right != null) {
return min(p.right);
}
return pre;
}
5.删除
根据key寻找当前节点并在每一次前进时记录当前节点为prev,继而分类讨论:
1)左子树为空,将右子树继承到prev
2)右子树为空,将左子树继承到prev
3)左右都存在,寻找后继,
后继与当前节点相邻:将后继节点继承到被删除节点的父节点上
后继与当前节点不相邻:将后继节点的右子树继承到后继节点的父节点上,
再将后继节点继承到被删除节点的父节点上,最后调整左右子节点为被删除节点的左右节点
//继承方法,将child通过curr与pre的节点关系继承到pre上,
//即删除curr,curr是左节点就将child集成到pre的左子树上
private void extend(BSTNode<KeyType, ValueType> pre, BSTNode<KeyType, ValueType> curr, BSTNode<KeyType, ValueType> child) {
if (pre == null) {
root = child;
} else if (pre.left == curr) {
pre.left = child;
} else {
pre.right = child;
}
}
public ValueType remove(KeyType key) {
BSTNode<KeyType, ValueType> p = root; //待删除节点
BSTNode<KeyType, ValueType> pre = null; //待删除节点的父节点
while (p != null) {
if (key.compareTo(p.key) < 0) {
pre = p;
p = p.left;
} else if (key.compareTo(p.key) > 0) {
pre = p;
p = p.right;
} else {
break;
}
}
if (p == null) { //未找到待删除节点
return null;
}
if (p.left == null) { //左子树为空
extend(pre, p, p.right);
} else if (p.right == null) { //右子树为空
extend(pre, p, p.left);
} else { //均不空,则寻找后继
BSTNode<KeyType, ValueType> s = p.right; //待删除后继
BSTNode<KeyType, ValueType> sprev = null; //待删除后继的父节点
while (s.left != null) { //寻找待删除后继
sprev = s;
s = s.left;
}
if (sprev.right != p) { //后继与待删除节点不相邻
extend(sprev, s, s.right);
s.right = p.right;
}
extend(pre, p, s);
s.left = p.left;
}
return p.value;
}
6.遍历
这里就不过多赘述了,直接上代码
public void inOrders() {//中序遍历
BSTNode<KeyType, ValueType> curr = root;
Stack<BSTNode<KeyType, ValueType>> stack = new Stack<>();
while (curr != null || !stack.isEmpty()) {
if (curr != null) {
stack.push(curr);
curr = curr.left;
} else {
BSTNode<KeyType, ValueType> pop = stack.pop();
System.out.println(pop.value);
curr = pop.right;
}
}
}
public void preOrders() {//前序遍历
preOrders(root);
}
private void preOrders(BSTNode<KeyType, ValueType> node) {
if (node == null) {
return;
}
System.out.print(node.value + "\t"); // 值
preOrders(node.left); // 左
preOrders(node.right); // 右
}
public void outOrders() {后序遍历
BSTNode<KeyType, ValueType> curr = root;
Stack<BSTNode<KeyType, ValueType>> stack = new Stack<>();
BSTNode<KeyType, ValueType> pop = null;
while (curr != null || !stack.isEmpty()) {
if (curr != null) {
stack.push(curr);
curr = curr.left;
} else {
BSTNode<KeyType, ValueType> peek = stack.peek();
if (peek.right == null || peek.right == pop) {
pop = stack.pop();
System.out.println(pop.value);
} else {
curr = peek.right;
}
}
}
}
三,实现
package BSTTree;
import java.util.Stack;
public class BSTTree<KeyType extends Comparable<KeyType>, ValueType>{
static class BSTNode<KeyType, ValueType> {
KeyType key;
ValueType value;
BSTNode<KeyType, ValueType> left;
BSTNode<KeyType, ValueType> right;
public BSTNode(KeyType key) {
this.key = key;
}
public BSTNode(KeyType key, ValueType value) {
this.key = key;
this.value = value;
}
public BSTNode(KeyType key, ValueType value, BSTNode<KeyType, ValueType> left, BSTNode<KeyType, ValueType> right) {
this.key = key;
this.value = value;
this.left = left;
this.right = right;
}
}
private BSTNode<KeyType, ValueType> root;
public ValueType min() {
return min(root).value;
}
public ValueType max() {
return max(root).value;
}
public ValueType get(KeyType key) {
BSTNode<KeyType, ValueType> p = root;
while (p != null) {
int result = key.compareTo(p.key);
if (result < 0) {
p = p.left;
} else if (result > 0) {
p = p.right;
} else {
return p.value;
}
}
return null;
}
public void put(KeyType key, ValueType value) {
BSTNode<KeyType, ValueType> p = root;
BSTNode<KeyType, ValueType> prev = null;
while (p != null) {
prev = p;
int result = key.compareTo(p.key);
if (result < 0) {
p = p.left;
} else if (result > 0) {
p = p.right;
} else {
p.value = value;
return;
}
}
if (prev == null) {
root = new BSTNode<KeyType, ValueType>(key, value);
return;
}
if (key.compareTo(prev.key) < 0) {
prev.left = new BSTNode<KeyType, ValueType>(key, value);
} else {
prev.right = new BSTNode<KeyType, ValueType>(key, value);
}
}
public void inOrders() {
BSTNode<KeyType, ValueType> curr = root;
Stack<BSTNode<KeyType, ValueType>> stack = new Stack<>();
while (curr != null || !stack.isEmpty()) {
if (curr != null) {
stack.push(curr);
curr = curr.left;
} else {
BSTNode<KeyType, ValueType> pop = stack.pop();
System.out.println(pop.value);
curr = pop.right;
}
}
}
public void preOrders() {
preOrders(root);
}
public void outOrders() {
BSTNode<KeyType, ValueType> curr = root;
Stack<BSTNode<KeyType, ValueType>> stack = new Stack<>();
BSTNode<KeyType, ValueType> pop = null;
while (curr != null || !stack.isEmpty()) {
if (curr != null) {
stack.push(curr);
curr = curr.left;
} else {
BSTNode<KeyType, ValueType> peek = stack.peek();
if (peek.right == null || peek.right == pop) {
pop = stack.pop();
System.out.println(pop.value);
} else {
curr = peek.right;
}
}
}
}
public ValueType findPrecursor(KeyType key) {
BSTNode<KeyType, ValueType> precursor = findPrecursor(root, key);
return precursor != null ? precursor.value : null;
}
public ValueType findSubsequent(KeyType key) {
BSTNode<KeyType, ValueType> subsequent = findSubsequent(root, key);
return subsequent != null ? subsequent.value : null;
}
public ValueType remove(KeyType key) {
BSTNode<KeyType, ValueType> p = root; //待删除节点
BSTNode<KeyType, ValueType> pre = null; //待删除节点的父节点
while (p != null) {
if (key.compareTo(p.key) < 0) {
pre = p;
p = p.left;
} else if (key.compareTo(p.key) > 0) {
pre = p;
p = p.right;
} else {
break;
}
}
if (p == null) { //未找到待删除节点
return null;
}
if (p.left == null) { //左子树为空
extend(pre, p, p.right);
} else if (p.right == null) { //右子树为空
extend(pre, p, p.left);
} else { //均不空,则寻找后继
BSTNode<KeyType, ValueType> s = p.right; //待删除后继
BSTNode<KeyType, ValueType> sprev = null; //待删除后继的父节点
while (s.left != null) { //寻找待删除后继
sprev = s;
s = s.left;
}
if (sprev.right != p) { //后继与待删除节点不相邻
extend(sprev, s, s.right);
s.right = p.right;
}
extend(pre, p, s);
s.left = p.left;
}
return p.value;
}
private void preOrders(BSTNode<KeyType, ValueType> node) {
if (node == null) {
return;
}
System.out.print(node.value + "\t"); // 值
preOrders(node.left); // 左
preOrders(node.right); // 右
}
private void extend(BSTNode<KeyType, ValueType> pre, BSTNode<KeyType, ValueType> curr, BSTNode<KeyType, ValueType> child) {
if (pre == null) {
root = child;
} else if (pre.left == curr) {
pre.left = child;
} else {
pre.right = child;
}
}
private BSTNode<KeyType, ValueType> findSubsequent(BSTNode<KeyType, ValueType> node, KeyType key) {
BSTNode<KeyType, ValueType> p = node;
BSTNode<KeyType, ValueType> pre = null;
while (p != null) {
if (key.compareTo(p.key) < 0) {
pre = p;
p = p.left;
} else if (key.compareTo(p.key) > 0) {
p = p.right;
} else {
break;
}
}
if (p == null) {
return null;
}
if (p.right != null) {
return min(p.right);
}
return pre;
}
private BSTNode<KeyType, ValueType> findPrecursor(BSTNode<KeyType, ValueType> node, KeyType key) {
BSTNode<KeyType, ValueType> p = node;
BSTNode<KeyType, ValueType> pre = null;
while (p != null) {
if (key.compareTo(p.key) < 0) {
p = p.left;
} else if (key.compareTo(p.key) > 0) {
pre = p;
p = p.right;
} else {
break;
}
}
if (p == null) {
return null;
}
if (p.left == null) {
return pre;
}
return max(p.left);
}
private BSTNode<KeyType, ValueType> max(BSTNode<KeyType, ValueType> node) {
if (node == null) {
return null;
}
BSTNode<KeyType, ValueType> p = node;
while (p.right != null) {
p = p.right;
}
return p;
}
private BSTNode<KeyType, ValueType> min(BSTNode<KeyType, ValueType> node) {
if (node == null) {
return null;
}
BSTNode<KeyType, ValueType> p = node;
while (p.left != null) {
p = p.left;
}
return p;
}