二叉查找树的基本储存单位是节点,每个节点包含:
1. 键,用来识别和排序一个节点。(如:一个单词)
2. 值,是键的附属信息。(如:单词的定义,发音等信息)
3. 左子树和右子树。
用途:可以根据键查找到相应的值。
二叉查找树是一棵二叉树,但是多了两个限制条件:
1. 每个节点都含有一个可排序的键(以及相关联的值)。
2. 每个节点的键都大于其左子树的任意节点,并小于右子树的任意节点。
优势:把链表插入的灵活性和二分查找的高效性结合起来。
PS:此处暂不考虑键相等问题。若要考虑,可把键相等节点归于左或右任意子树,或者在每个节点存储一个count记录个数。
节点
private class Node{
private Key key;
private Value val;
private Node left, right;
private int N;
public Node(Key key, Value val){
this.key = key;
this.val = val;
}
}
添加
public Node put(Key key, Value val){
Node node = new Node(key, val);
Node tem = root;
if (root == null){
return root = node;
}
while (tem != null){
int cmp = key.compareTo(tem.key);
if (cmp < 0 ) {
if (tem.left == null) return tem.left = node;
tem = tem.left;
}
else if (cmp > 0){
if (tem.right == null) return tem.right = node;
tem = tem.right;
}
else {
tem.val = val;
break;
}
}
return node;
}
查询
public Value get(Key key){
Node tem = root;
while (tem != null){
int cmp = key.compareTo(root.key);
if (cmp < 0) tem = tem.left;
else if (cmp > 0) tem = tem.right;
else return tem.val;
}
return null;
}
删除
public boolean delete(Key key){
Node ans = delete(root, key);
if (ans == null && root != null && (root.left != null || root.right != null)) return false;
root = ans;
return true;
}
private Node delete(Node x, Key key){
if (x == null) return null;
int cmp = key.compareTo(x.key);
if (cmp < 0) x.left = delete(x.left, key);
else if (cmp > 0) x.right = delete(x.right, key);
else {
if (x.right == null) return x.left;
if (x.left == null) return x.right;
Node t = x;
while (x.left != null) x = x.left;
x.left = t.left;
x.right = deleteMin(t.right);
}
return x;
}
private Node deleteMin(Node x){
if (x.left == null) return x.right;
x.left = deleteMin(x.left);
return x;
}
升序打印
//中序遍历
public void show(){
Stack<Node> stack = new Stack();
Node tem = root;
while (tem != null || !stack.isEmpty()){
while (tem != null){
stack.push(tem);
tem = tem.left;
}
tem = stack.pop();
System.out.print(tem.key + " ");
tem = tem.right;
}
}
问题:可能会出现极不平衡的树,效率会很低。