问题:
说明:
来 写 一 个 BST。
问题链接:https://loj.ac/problem/104
提交记录:
https://loj.ac/submission/889961
输入案例:
传了一份测试数据:https://download.youkuaiyun.com/download/qq_28033719/12709334 (假装)
我的代码:
准备知识
1、以往知识:
左旋转 右旋转 前驱 后继 https://blog.youkuaiyun.com/qq_28033719/article/details/107316144
2、二叉搜索树:
把二分法玩的飞起的树,后来红黑树也基于这个来玩。
3、插入
没有单双旋,只是找到位置插入就行,不过因为 AVL 反而是基于这个来搞得,所以先写个 BST 模板
具体代码
因为 Splay 、 Treap 都玩过了,所以这个可以默写一次,不过还是有点错。
import java.util.Scanner;
public class BST {
class Node {
int val;
Node left;
Node right;
int num;
int size;
Node(int val) {
this.val = val;
this.num = 1;
}
}
Node root;
public void pushup(Node r) {
if(r == null) return;
int left = r.left == null ? 0 : r.left.size;
int right = r.right == null ? 0 : r.right.size;
r.size = left + right + r.num;
}
public Node insert(Node r, int v) {
if(r == null) r = new Node(v);
else if(r.val == v) r.num ++;
else if(r.val > v) r.left = insert(r.left, v);
else r.right = insert(r.right, v);
pushup(r);
return r;
}
public void clear(Node r) {
if(r != null) {
r.left = null;
r.right = null;
}
}
public Node delete(Node r, int v) {
if(r == null) return r;
else if(r.val < v) r.right = delete(r.right, v);
else if(r.val > v) r.left = delete(r.left, v);
else {
r.num --;
if(r.num == 0) {
boolean ln = r.left == null;
boolean rn = r.right == null;
if(ln && rn) return null;
else if(ln) {
Node res = r.right;
clear(r);
return res;
}
else if(rn) {
Node res = r.left;
clear(r);
return res;
}
else {
Node res = deletemin(r.left);
res.left = res.val == r.left.val ? r.left.left : r.left;
res.right = r.right;
clear(r);
pushup(res);
return res;
}
}
}
pushup(r);
return r;
}
public Node deletemin(Node r) {
if(r.right == null) return r;
else {
Node res = deletemin(r.right);
// 这里需要把找到的左边最大值拿回来,要小心它还有个 left
if(r.right.val == res.val) r.right = res.left;
r.size -= res.num;
return res;
}
}
public int find(Node r, int n) {
if(r == null) return 0;
// 只弄个 r.left ,加上了 r.num 值,排名上 r.num 在判断中出错
int left = r.left == null ? 0 : r.left.size;
if(left >= n) return find(r.left, n);
else if(n > left + r.num) return find(r.right, n - left - r.num);
return r.val;
}
public int rank(Node r, int v) {
if(r == null) return Integer.MIN_VALUE;
else if(r.val > v) return rank(r.left, v);
else if(r.val < v) return r.num + rank(r.right, v) + (r.left == null ? 0 : r.left.size);
else return r.left == null ? 1 : r.left.size + 1;
}
public int pre(Node r, int v) {
if(r == null) return Integer.MIN_VALUE;
else if(r.val >= v) return pre(r.left, v);
else return Math.max(r.val, pre(r.right, v));
}
public int sub(Node r, int v) {
if(r == null) return Integer.MAX_VALUE;
else if(r.val <= v) return sub(r.right, v);
else return Math.min(r.val, sub(r.left, v));
}
public Node findMax(Node r) {
if(r == null || r.right == null) return r;
else return findMax(r.right);
}
public Node findMin(Node r) {
if(r == null || r.left == null) return r;
else return findMin(r.left);
}
public static void main(String[] args) {
BST tree = new BST();
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
while(n -- > 0) {
int op = sc.nextInt();
int v = sc.nextInt();
switch (op) {
case 1 : tree.root = tree.insert(tree.root, v);break;
case 2 : tree.root = tree.delete(tree.root, v);break;
case 3 : System.out.println(tree.rank(tree.root, v));break;
case 4 : System.out.println(tree.find(tree.root, v));break;
case 5 : System.out.println(tree.pre(tree.root, v));break;
case 6 : System.out.println(tree.sub(tree.root, v));break;
case 7 :
Node max = tree.findMax(tree.root);
System.out.println(max == null ? 0 : max.val); break;
case 8 :
Node min = tree.findMin(tree.root);
System.out.println(min == null ? 0 : min.val); break;
}
}
}
}