pull/6/head
左程云 4 years ago
parent 359d69732b
commit 946360f90f

@ -12,6 +12,17 @@ public class Code01_MorrisTraversal {
}
}
public static void process(Node root) {
if (root == null) {
return;
}
// 1
process(root.left);
// 2
process(root.right);
// 3
}
public static void morris(Node head) {
if (head == null) {
return;
@ -19,20 +30,16 @@ public class Code01_MorrisTraversal {
Node cur = head;
Node mostRight = null;
while (cur != null) {
// cur有没有左树
mostRight = cur.left;
if (mostRight != null) { // 有左树的情况下
// 找到cur左树上真实的最右
if (mostRight != null) {
while (mostRight.right != null && mostRight.right != cur) {
mostRight = mostRight.right;
}
// 从while中出来mostRight一定是cur左树上的最右节点
// mostRight
if (mostRight.right == null) {
mostRight.right = cur;
cur = cur.left;
continue;
} else { // mostRight.right != null -> mostRight.right == cur
} else {
mostRight.right = null;
}
}
@ -40,7 +47,7 @@ public class Code01_MorrisTraversal {
}
}
public static void morrisIn(Node head) {
public static void morrisPre(Node head) {
if (head == null) {
return;
}
@ -53,43 +60,43 @@ public class Code01_MorrisTraversal {
mostRight = mostRight.right;
}
if (mostRight.right == null) {
System.out.print(cur.value + " ");
mostRight.right = cur;
cur = cur.left;
continue;
} else {
mostRight.right = null;
}
} else {
System.out.print(cur.value + " ");
}
System.out.print(cur.value + " ");
cur = cur.right;
}
System.out.println();
}
public static void morrisPre(Node head) {
public static void morrisIn(Node head) {
if (head == null) {
return;
}
Node cur1 = head;
Node cur2 = null;
while (cur1 != null) {
cur2 = cur1.left;
if (cur2 != null) {
while (cur2.right != null && cur2.right != cur1) {
cur2 = cur2.right;
Node cur = head;
Node mostRight = null;
while (cur != null) {
mostRight = cur.left;
if (mostRight != null) {
while (mostRight.right != null && mostRight.right != cur) {
mostRight = mostRight.right;
}
if (cur2.right == null) {
cur2.right = cur1;
System.out.print(cur1.value + " ");
cur1 = cur1.left;
if (mostRight.right == null) {
mostRight.right = cur;
cur = cur.left;
continue;
} else {
cur2.right = null;
mostRight.right = null;
}
} else {
System.out.print(cur1.value + " ");
}
cur1 = cur1.right;
System.out.print(cur.value + " ");
cur = cur.right;
}
System.out.println();
}

@ -19,6 +19,7 @@ public class Code05_MinHeight {
return p(head);
}
// 返回x为头的树最小深度是多少
public static int p(Node x) {
if (x.left == null && x.right == null) {
return 1;

@ -5,7 +5,7 @@ public class Code01_SegmentTree {
public static class SegmentTree {
// arr[]为原序列的信息从0开始但在arr里是从1开始的
// sum[]模拟线段树维护区间和
// lazy[]为累加懒惰标记
// lazy[]为累加懒惰标记
// change[]为更新的值
// update[]为更新慵懒标记
private int MAXN;
@ -17,12 +17,11 @@ public class Code01_SegmentTree {
public SegmentTree(int[] origin) {
MAXN = origin.length + 1;
arr = new int[MAXN]; // arr[0] 不用 从1开始使用
arr = new int[MAXN]; // arr[0] 不用 从1开始使用
for (int i = 1; i < MAXN; i++) {
arr[i] = origin[i - 1];
}
sum = new int[MAXN << 2]; // 用来支持脑补概念中,某一个范围的累加和信息
lazy = new int[MAXN << 2]; // 用来支持脑补概念中,某一个范围沒有往下傳遞的纍加任務
change = new int[MAXN << 2]; // 用来支持脑补概念中,某一个范围有没有更新操作的任务
update = new boolean[MAXN << 2]; // 用来支持脑补概念中,某一个范围更新任务,更新成了什么
@ -58,7 +57,7 @@ public class Code01_SegmentTree {
// 在初始化阶段先把sum数组填好
// 在arr[l~r]范围上去build1~N
// rt : 这个范围在sum中的下标
// rt : 这个范围在sum中的下标
public void build(int l, int r, int rt) {
if (l == r) {
sum[rt] = arr[l];
@ -70,6 +69,9 @@ public class Code01_SegmentTree {
pushUp(rt);
}
// L~R 所有的值变成C
// l~r rt
public void update(int L, int R, int C, int l, int r, int rt) {
if (L <= l && r <= R) {
update[rt] = true;
@ -90,38 +92,30 @@ public class Code01_SegmentTree {
pushUp(rt);
}
// L..R -> 任务范围 ,所有的值累加上C
// l,r -> 表达的范围
// rt 去哪找lr范围上的信息
public void add(
int L, int R, int C,
int l, int r,
int rt) {
// 任务的范围彻底覆盖了,当前表达的范围
// L~R, C 任务!
// rtl~r
public void add(int L, int R, int C, int l, int r, int rt) {
// 任务如果把此时的范围全包了!
if (L <= l && r <= R) {
sum[rt] += C * (r - l + 1);
lazy[rt] += C;
return;
}
// 任务并没有把l...r全包住
// 要把当前任务往下发
// 任务 L, R 没有把本身表达范围 l,r 彻底包住
int mid = (l + r) >> 1; // l..mid (rt << 1) mid+1...r(rt << 1 | 1)
// 下发之前所有攒的懒任务
// 任务没有把你全包!
// l r mid = (l+r)/2
int mid = (l + r) >> 1;
pushDown(rt, mid - l + 1, r - mid);
// 左孩子是否需要接到任务
// L~R
if (L <= mid) {
add(L, R, C, l, mid, rt << 1);
}
// 右孩子是否需要接到任务
if (R > mid) {
add(L, R, C, mid + 1, r, rt << 1 | 1);
}
// 左右孩子做完任务后我更新我的sum信息
pushUp(rt);
}
// 1~6 累加和是多少? 1~8 rt
// 1~6 累加和是多少? 1~8 rt
public long query(int L, int R, int l, int r, int rt) {
if (L <= l && r <= R) {
return sum[rt];

@ -15,7 +15,7 @@ public class Code02_FallingSquares {
public SegmentTree(int size) {
int N = size + 1;
max = new int[N << 2];
change = new int[N << 2];
update = new boolean[N << 2];
}
@ -74,11 +74,6 @@ public class Code02_FallingSquares {
}
// positions
// [2,7] -> 2 , 8
// [3, 10] -> 3, 12
//
//
public HashMap<Integer, Integer> index(int[][] positions) {
TreeSet<Integer> pos = new TreeSet<>();
for (int[] arr : positions) {
@ -95,9 +90,7 @@ public class Code02_FallingSquares {
public List<Integer> fallingSquares(int[][] positions) {
HashMap<Integer, Integer> map = index(positions);
// 100 -> 1 306 -> 2 403 -> 3
// [100,403] 1~3
int N = map.size(); // 1 ~ N
int N = map.size();
SegmentTree segmentTree = new SegmentTree(N);
int max = 0;
List<Integer> res = new ArrayList<>();

@ -0,0 +1,48 @@
package class33;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.Security;
import javax.xml.bind.DatatypeConverter;
public class Hash {
private MessageDigest hash;
public Hash(String algorithm) {
try {
hash = MessageDigest.getInstance(algorithm);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
public String hashCode(String input) {
return DatatypeConverter.printHexBinary(hash.digest(input.getBytes())).toUpperCase();
}
public static void main(String[] args) {
System.out.println("支持的算法 : ");
for (String str : Security.getAlgorithms("MessageDigest")) {
System.out.println(str);
}
System.out.println("=======");
String algorithm = "SHA";
Hash hash = new Hash(algorithm);
String input1 = "zuochengyunzuochengyun1";
String input2 = "zuochengyunzuochengyun2";
String input3 = "zuochengyunzuochengyun3";
String input4 = "zuochengyunzuochengyun4";
String input5 = "zuochengyunzuochengyun5";
System.out.println(hash.hashCode(input1));
System.out.println(hash.hashCode(input2));
System.out.println(hash.hashCode(input3));
System.out.println(hash.hashCode(input4));
System.out.println(hash.hashCode(input5));
}
}

@ -0,0 +1,2 @@
本章并无code因为资源限制类题目代码量巨大需要整个工程的设计
面试中主要和面试官聊解法,也不会让代码实现

@ -0,0 +1,257 @@
package class35;
public class Code01_AVLTreeMap {
public static class AVLNode<K extends Comparable<K>, V> {
public K k;
public V v;
public AVLNode<K, V> l;
public AVLNode<K, V> r;
public int h;
public AVLNode(K key, V value) {
k = key;
v = value;
h = 1;
}
}
public static class AVLTreeMap<K extends Comparable<K>, V> {
private AVLNode<K, V> root;
private int size;
public AVLTreeMap() {
root = null;
size = 0;
}
private AVLNode<K, V> rightRotate(AVLNode<K, V> cur) {
AVLNode<K, V> left = cur.l;
cur.l = left.r;
left.r = cur;
cur.h = Math.max((cur.l != null ? cur.l.h : 0), (cur.r != null ? cur.r.h : 0)) + 1;
left.h = Math.max((left.l != null ? left.l.h : 0), (left.r != null ? left.r.h : 0)) + 1;
return left;
}
private AVLNode<K, V> leftRotate(AVLNode<K, V> cur) {
AVLNode<K, V> right = cur.r;
cur.r = right.l;
right.l = cur;
cur.h = Math.max((cur.l != null ? cur.l.h : 0), (cur.r != null ? cur.r.h : 0)) + 1;
right.h = Math.max((right.l != null ? right.l.h : 0), (right.r != null ? right.r.h : 0)) + 1;
return right;
}
private AVLNode<K, V> maintain(AVLNode<K, V> cur) {
if (cur == null) {
return null;
}
int leftHeight = cur.l != null ? cur.l.h : 0;
int rightHeight = cur.r != null ? cur.r.h : 0;
if (Math.abs(leftHeight - rightHeight) > 1) {
if (leftHeight > rightHeight) {
int leftLeftHeight = cur.l != null && cur.l.l != null ? cur.l.l.h : 0;
int leftRightHeight = cur.l != null && cur.l.r != null ? cur.l.r.h : 0;
if (leftLeftHeight >= leftRightHeight) {
cur = rightRotate(cur);
} else {
cur.l = leftRotate(cur.l);
cur = rightRotate(cur);
}
} else {
int rightLeftHeight = cur.r != null && cur.r.l != null ? cur.r.l.h : 0;
int rightRightHeight = cur.r != null && cur.r.r != null ? cur.r.r.h : 0;
if (rightRightHeight >= rightLeftHeight) {
cur = leftRotate(cur);
} else {
cur.r = rightRotate(cur.r);
cur = leftRotate(cur);
}
}
}
return cur;
}
private AVLNode<K, V> findLastIndex(K key) {
AVLNode<K, V> pre = root;
AVLNode<K, V> cur = root;
while (cur != null) {
pre = cur;
if (key.compareTo(cur.k) == 0) {
break;
} else if (key.compareTo(cur.k) < 0) {
cur = cur.l;
} else {
cur = cur.r;
}
}
return pre;
}
private AVLNode<K, V> findLastNoSmallIndex(K key) {
AVLNode<K, V> ans = null;
AVLNode<K, V> cur = root;
while (cur != null) {
if (key.compareTo(cur.k) == 0) {
ans = cur;
break;
} else if (key.compareTo(cur.k) < 0) {
ans = cur;
cur = cur.l;
} else {
cur = cur.r;
}
}
return ans;
}
private AVLNode<K, V> findLastNoBigIndex(K key) {
AVLNode<K, V> ans = null;
AVLNode<K, V> cur = root;
while (cur != null) {
if (key.compareTo(cur.k) == 0) {
ans = cur;
break;
} else if (key.compareTo(cur.k) < 0) {
cur = cur.l;
} else {
ans = cur;
cur = cur.r;
}
}
return ans;
}
private AVLNode<K, V> add(AVLNode<K, V> cur, K key, V value) {
if (cur == null) {
return new AVLNode<K, V>(key, value);
} else {
if (key.compareTo(cur.k) < 0) {
cur.l = add(cur.l, key, value);
} else {
cur.r = add(cur.r, key, value);
}
cur.h = Math.max(cur.l != null ? cur.l.h : 0, cur.r != null ? cur.r.h : 0) + 1;
return maintain(cur);
}
}
// 在cur这棵树上删掉key所代表的节点
// 返回cur这棵树的新头部
private AVLNode<K, V> delete(AVLNode<K, V> cur, K key) {
if (key.compareTo(cur.k) > 0) {
cur.r = delete(cur.r, key);
} else if (key.compareTo(cur.k) < 0) {
cur.l = delete(cur.l, key);
} else {
if (cur.l == null && cur.r == null) {
cur = null;
} else if (cur.l == null && cur.r != null) {
cur = cur.r;
} else if (cur.l != null && cur.r == null) {
cur = cur.l;
} else {
AVLNode<K, V> des = cur.r;
while (des.l != null) {
des = des.l;
}
cur.r = delete(cur.r, des.k);
des.l = cur.l;
des.r = cur.r;
cur = des;
}
}
if (cur != null) {
cur.h = Math.max(cur.l != null ? cur.l.h : 0, cur.r != null ? cur.r.h : 0) + 1;
}
return maintain(cur);
}
public int size() {
return size;
}
public boolean containsKey(K key) {
if (key == null) {
return false;
}
AVLNode<K, V> lastNode = findLastIndex(key);
return lastNode != null && key.compareTo(lastNode.k) == 0 ? true : false;
}
public void put(K key, V value) {
if (key == null) {
return;
}
AVLNode<K, V> lastNode = findLastIndex(key);
if (lastNode != null && key.compareTo(lastNode.k) == 0) {
lastNode.v = value;
} else {
size++;
root = add(root, key, value);
}
}
public void remove(K key) {
if (key == null) {
return;
}
if (containsKey(key)) {
size--;
root = delete(root, key);
}
}
public V get(K key) {
if (key == null) {
return null;
}
AVLNode<K, V> lastNode = findLastIndex(key);
if (lastNode != null && key.compareTo(lastNode.k) == 0) {
return lastNode.v;
}
return null;
}
public K firstKey() {
if (root == null) {
return null;
}
AVLNode<K, V> cur = root;
while (cur.l != null) {
cur = cur.l;
}
return cur.k;
}
public K lastKey() {
if (root == null) {
return null;
}
AVLNode<K, V> cur = root;
while (cur.r != null) {
cur = cur.r;
}
return cur.k;
}
public K floorKey(K key) {
if (key == null) {
return null;
}
AVLNode<K, V> lastNoBigNode = findLastNoBigIndex(key);
return lastNoBigNode == null ? null : lastNoBigNode.k;
}
public K ceilingKey(K key) {
if (key == null) {
return null;
}
AVLNode<K, V> lastNoSmallNode = findLastNoSmallIndex(key);
return lastNoSmallNode == null ? null : lastNoSmallNode.k;
}
}
}

@ -0,0 +1,360 @@
package class36;
public class Code01_SizeBalancedTreeMap {
public static class SBTNode<K extends Comparable<K>, V> {
public K key;
public V value;
public SBTNode<K, V> l;
public SBTNode<K, V> r;
public int size; // 不同的key的数量
public SBTNode(K key, V value) {
this.key = key;
this.value = value;
size = 1;
}
}
public static class SizeBalancedTreeMap<K extends Comparable<K>, V> {
private SBTNode<K, V> root;
private SBTNode<K, V> rightRotate(SBTNode<K, V> cur) {
SBTNode<K, V> leftNode = cur.l;
cur.l = leftNode.r;
leftNode.r = cur;
leftNode.size = cur.size;
cur.size = (cur.l != null ? cur.l.size : 0) + (cur.r != null ? cur.r.size : 0) + 1;
return leftNode;
}
private SBTNode<K, V> leftRotate(SBTNode<K, V> cur) {
SBTNode<K, V> rightNode = cur.r;
cur.r = rightNode.l;
rightNode.l = cur;
rightNode.size = cur.size;
cur.size = (cur.l != null ? cur.l.size : 0) + (cur.r != null ? cur.r.size : 0) + 1;
return rightNode;
}
private SBTNode<K, V> maintain(SBTNode<K, V> cur) {
if (cur == null) {
return null;
}
int leftSize = cur.l != null ? cur.l.size : 0;
int leftLeftSize = cur.l != null && cur.l.l != null ? cur.l.l.size : 0;
int leftRightSize = cur.l != null && cur.l.r != null ? cur.l.r.size : 0;
int rightSize = cur.r != null ? cur.r.size : 0;
int rightLeftSize = cur.r != null && cur.r.l != null ? cur.r.l.size : 0;
int rightRightSize = cur.r != null && cur.r.r != null ? cur.r.r.size : 0;
if (leftLeftSize > rightSize) {
cur = rightRotate(cur);
cur.r = maintain(cur.r);
cur = maintain(cur);
} else if (leftRightSize > rightSize) {
cur.l = leftRotate(cur.l);
cur = rightRotate(cur);
cur.l = maintain(cur.l);
cur.r = maintain(cur.r);
cur = maintain(cur);
} else if (rightRightSize > leftSize) {
cur = leftRotate(cur);
cur.l = maintain(cur.l);
cur = maintain(cur);
} else if (rightLeftSize > leftSize) {
cur.r = rightRotate(cur.r);
cur = leftRotate(cur);
cur.l = maintain(cur.l);
cur.r = maintain(cur.r);
cur = maintain(cur);
}
return cur;
}
private SBTNode<K, V> findLastIndex(K key) {
SBTNode<K, V> pre = root;
SBTNode<K, V> cur = root;
while (cur != null) {
pre = cur;
if (key.compareTo(cur.key) == 0) {
break;
} else if (key.compareTo(cur.key) < 0) {
cur = cur.l;
} else {
cur = cur.r;
}
}
return pre;
}
private SBTNode<K, V> findLastNoSmallIndex(K key) {
SBTNode<K, V> ans = null;
SBTNode<K, V> cur = root;
while (cur != null) {
if (key.compareTo(cur.key) == 0) {
ans = cur;
break;
} else if (key.compareTo(cur.key) < 0) {
ans = cur;
cur = cur.l;
} else {
cur = cur.r;
}
}
return ans;
}
private SBTNode<K, V> findLastNoBigIndex(K key) {
SBTNode<K, V> ans = null;
SBTNode<K, V> cur = root;
while (cur != null) {
if (key.compareTo(cur.key) == 0) {
ans = cur;
break;
} else if (key.compareTo(cur.key) < 0) {
cur = cur.l;
} else {
ans = cur;
cur = cur.r;
}
}
return ans;
}
// 现在以cur为头的树上新增加(key, value)这样的记录
// 加完之后会对cur做检查该调整调整
// 返回,调整完之后,整棵树的新头部
private SBTNode<K, V> add(SBTNode<K, V> cur, K key, V value) {
if (cur == null) {
return new SBTNode<K, V>(key, value);
} else {
cur.size++;
if (key.compareTo(cur.key) < 0) {
cur.l = add(cur.l, key, value);
} else {
cur.r = add(cur.r, key, value);
}
return maintain(cur);
}
}
// 在cur这棵树上删掉key所代表的节点
// 返回cur这棵树的新头部
private SBTNode<K, V> delete(SBTNode<K, V> cur, K key) {
cur.size--;
if (key.compareTo(cur.key) > 0) {
cur.r = delete(cur.r, key);
} else if (key.compareTo(cur.key) < 0) {
cur.l = delete(cur.l, key);
} else { // 当前要删掉cur
if (cur.l == null && cur.r == null) {
// free cur memory -> C++
cur = null;
} else if (cur.l == null && cur.r != null) {
// free cur memory -> C++
cur = cur.r;
} else if (cur.l != null && cur.r == null) {
// free cur memory -> C++
cur = cur.l;
} else { // 有左有右
SBTNode<K, V> pre = null;
SBTNode<K, V> des = cur.r;
des.size--;
while (des.l != null) {
pre = des;
des = des.l;
des.size--;
}
if (pre != null) {
pre.l = des.r;
des.r = cur.r;
}
des.l = cur.l;
des.size = des.l.size + (des.r == null ? 0 : des.r.size) + 1;
// free cur memory -> C++
cur = des;
}
}
// cur = maintain(cur);
return cur;
}
private SBTNode<K, V> getIndex(SBTNode<K, V> cur, int kth) {
if (kth == (cur.l != null ? cur.l.size : 0) + 1) {
return cur;
} else if (kth <= (cur.l != null ? cur.l.size : 0)) {
return getIndex(cur.l, kth);
} else {
return getIndex(cur.r, kth - (cur.l != null ? cur.l.size : 0) - 1);
}
}
public int size() {
return root == null ? 0 : root.size;
}
public boolean containsKey(K key) {
if (key == null) {
throw new RuntimeException("invalid parameter.");
}
SBTNode<K, V> lastNode = findLastIndex(key);
return lastNode != null && key.compareTo(lastNode.key) == 0 ? true : false;
}
// keyvalue put -> 有序表 新增、改value
public void put(K key, V value) {
if (key == null) {
throw new RuntimeException("invalid parameter.");
}
SBTNode<K, V> lastNode = findLastIndex(key);
if (lastNode != null && key.compareTo(lastNode.key) == 0) {
lastNode.value = value;
} else {
root = add(root, key, value);
}
}
public void remove(K key) {
if (key == null) {
throw new RuntimeException("invalid parameter.");
}
if (containsKey(key)) {
root = delete(root, key);
}
}
public K getIndexKey(int index) {
if (index < 0 || index >= this.size()) {
throw new RuntimeException("invalid parameter.");
}
return getIndex(root, index + 1).key;
}
public V getIndexValue(int index) {
if (index < 0 || index >= this.size()) {
throw new RuntimeException("invalid parameter.");
}
return getIndex(root, index + 1).value;
}
public V get(K key) {
if (key == null) {
throw new RuntimeException("invalid parameter.");
}
SBTNode<K, V> lastNode = findLastIndex(key);
if (lastNode != null && key.compareTo(lastNode.key) == 0) {
return lastNode.value;
} else {
return null;
}
}
public K firstKey() {
if (root == null) {
return null;
}
SBTNode<K, V> cur = root;
while (cur.l != null) {
cur = cur.l;
}
return cur.key;
}
public K lastKey() {
if (root == null) {
return null;
}
SBTNode<K, V> cur = root;
while (cur.r != null) {
cur = cur.r;
}
return cur.key;
}
public K floorKey(K key) {
if (key == null) {
throw new RuntimeException("invalid parameter.");
}
SBTNode<K, V> lastNoBigNode = findLastNoBigIndex(key);
return lastNoBigNode == null ? null : lastNoBigNode.key;
}
public K ceilingKey(K key) {
if (key == null) {
throw new RuntimeException("invalid parameter.");
}
SBTNode<K, V> lastNoSmallNode = findLastNoSmallIndex(key);
return lastNoSmallNode == null ? null : lastNoSmallNode.key;
}
}
// for test
public static void printAll(SBTNode<String, Integer> head) {
System.out.println("Binary Tree:");
printInOrder(head, 0, "H", 17);
System.out.println();
}
// for test
public static void printInOrder(SBTNode<String, Integer> head, int height, String to, int len) {
if (head == null) {
return;
}
printInOrder(head.r, height + 1, "v", len);
String val = to + "(" + head.key + "," + head.value + ")" + to;
int lenM = val.length();
int lenL = (len - lenM) / 2;
int lenR = len - lenM - lenL;
val = getSpace(lenL) + val + getSpace(lenR);
System.out.println(getSpace(height * len) + val);
printInOrder(head.l, height + 1, "^", len);
}
// for test
public static String getSpace(int num) {
String space = " ";
StringBuffer buf = new StringBuffer("");
for (int i = 0; i < num; i++) {
buf.append(space);
}
return buf.toString();
}
public static void main(String[] args) {
SizeBalancedTreeMap<String, Integer> sbt = new SizeBalancedTreeMap<String, Integer>();
sbt.put("d", 4);
sbt.put("c", 3);
sbt.put("a", 1);
sbt.put("b", 2);
// sbt.put("e", 5);
sbt.put("g", 7);
sbt.put("f", 6);
sbt.put("h", 8);
sbt.put("i", 9);
sbt.put("a", 111);
System.out.println(sbt.get("a"));
sbt.put("a", 1);
System.out.println(sbt.get("a"));
for (int i = 0; i < sbt.size(); i++) {
System.out.println(sbt.getIndexKey(i) + " , " + sbt.getIndexValue(i));
}
printAll(sbt.root);
System.out.println(sbt.firstKey());
System.out.println(sbt.lastKey());
System.out.println(sbt.floorKey("g"));
System.out.println(sbt.ceilingKey("g"));
System.out.println(sbt.floorKey("e"));
System.out.println(sbt.ceilingKey("e"));
System.out.println(sbt.floorKey(""));
System.out.println(sbt.ceilingKey(""));
System.out.println(sbt.floorKey("j"));
System.out.println(sbt.ceilingKey("j"));
sbt.remove("d");
printAll(sbt.root);
sbt.remove("f");
printAll(sbt.root);
}
}

@ -0,0 +1,248 @@
package class36;
import java.util.ArrayList;
public class Code02_SkipListMap {
// 跳表的节点定义
public static class SkipListNode<K extends Comparable<K>, V> {
public K key;
public V val;
public ArrayList<SkipListNode<K, V>> nextNodes;
public SkipListNode(K k, V v) {
key = k;
val = v;
nextNodes = new ArrayList<SkipListNode<K, V>>();
}
// 遍历的时候如果是往右遍历到的null(next == null), 遍历结束
// 头(null), 头节点的null认为最小
// node -> 头node(null, "") node.isKeyLess(!null) true
// node里面的key是否比otherKey小true不是false
public boolean isKeyLess(K otherKey) {
// otherKey == null -> false
return otherKey != null && (key == null || key.compareTo(otherKey) < 0);
}
public boolean isKeyEqual(K otherKey) {
return (key == null && otherKey == null)
|| (key != null && otherKey != null && key.compareTo(otherKey) == 0);
}
}
public static class SkipListMap<K extends Comparable<K>, V> {
private static final double PROBABILITY = 0.5; // < 0.5 继续做,>=0.5 停
private SkipListNode<K, V> head;
private int size;
private int maxLevel;
public SkipListMap() {
head = new SkipListNode<K, V>(null, null);
head.nextNodes.add(null); // 0
size = 0;
maxLevel = 0;
}
// 从最高层开始,一路找下去,
// 最终找到第0层的<key的最右的节点
private SkipListNode<K, V> mostRightLessNodeInTree(K key) {
if (key == null) {
return null;
}
int level = maxLevel;
SkipListNode<K, V> cur = head;
while (level >= 0) { // 从上层跳下层
// cur level -> level-1
cur = mostRightLessNodeInLevel(key, cur, level--);
}
return cur;
}
// 在level层里如何往右移动
// 现在来到的节点是cur来到了cur的level层在level层上找到<key最后一个节点并返回
private SkipListNode<K, V> mostRightLessNodeInLevel(K key,
SkipListNode<K, V> cur,
int level) {
SkipListNode<K, V> next = cur.nextNodes.get(level);
while (next != null && next.isKeyLess(key)) {
cur = next;
next = cur.nextNodes.get(level);
}
return cur;
}
public boolean containsKey(K key) {
if (key == null) {
return false;
}
SkipListNode<K, V> less = mostRightLessNodeInTree(key);
SkipListNode<K, V> next = less.nextNodes.get(0);
return next != null && next.isKeyEqual(key);
}
// 新增、改value
public void put(K key, V value) {
if (key == null) {
return;
}
// 0层上最右一个< key 的Node -> >key
SkipListNode<K, V> less = mostRightLessNodeInTree(key);
SkipListNode<K, V> find = less.nextNodes.get(0);
if (find != null && find.isKeyEqual(key)) {
find.val = value;
} else { // find == null 8 7 9
size++;
int newNodeLevel = 0;
while (Math.random() < PROBABILITY) {
newNodeLevel++;
}
// newNodeLevel
while (newNodeLevel > maxLevel) {
head.nextNodes.add(null);
maxLevel++;
}
SkipListNode<K, V> newNode = new SkipListNode<K, V>(key, value);
for (int i = 0; i <= newNodeLevel; i++) {
newNode.nextNodes.add(null);
}
int level = maxLevel;
SkipListNode<K, V> pre = head;
while (level >= 0) {
// level 层中,找到最右的 < key 的节点
pre = mostRightLessNodeInLevel(key, pre, level);
if (level <= newNodeLevel) {
newNode.nextNodes.set(level, pre.nextNodes.get(level));
pre.nextNodes.set(level, newNode);
}
level--;
}
}
}
public V get(K key) {
if (key == null) {
return null;
}
SkipListNode<K, V> less = mostRightLessNodeInTree(key);
SkipListNode<K, V> next = less.nextNodes.get(0);
return next != null && next.isKeyEqual(key) ? next.val : null;
}
public void remove(K key) {
if (containsKey(key)) {
size--;
int level = maxLevel;
SkipListNode<K, V> pre = head;
while (level >= 0) {
pre = mostRightLessNodeInLevel(key, pre, level);
SkipListNode<K, V> next = pre.nextNodes.get(level);
// 1在这一层中pre下一个就是key
// 2在这一层中pre的下一个key是>要删除key
if (next != null && next.isKeyEqual(key)) {
// free delete node memory -> C++
// level : pre -> next(key) -> ...
pre.nextNodes.set(level, next.nextNodes.get(level));
}
// 在level层只有一个节点了就是默认节点head
if (level != 0 && pre == head && pre.nextNodes.get(level) == null) {
head.nextNodes.remove(level);
maxLevel--;
}
level--;
}
}
}
public K firstKey() {
return head.nextNodes.get(0) != null ? head.nextNodes.get(0).key : null;
}
public K lastKey() {
int level = maxLevel;
SkipListNode<K, V> cur = head;
while (level >= 0) {
SkipListNode<K, V> next = cur.nextNodes.get(level);
while (next != null) {
cur = next;
next = cur.nextNodes.get(level);
}
level--;
}
return cur.key;
}
public K ceilingKey(K key) {
if (key == null) {
return null;
}
SkipListNode<K, V> less = mostRightLessNodeInTree(key);
SkipListNode<K, V> next = less.nextNodes.get(0);
return next != null ? next.key : null;
}
public K floorKey(K key) {
if (key == null) {
return null;
}
SkipListNode<K, V> less = mostRightLessNodeInTree(key);
SkipListNode<K, V> next = less.nextNodes.get(0);
return next != null && next.isKeyEqual(key) ? next.key : less.key;
}
public int size() {
return size;
}
}
// for test
public static void printAll(SkipListMap<String, String> obj) {
for (int i = obj.maxLevel; i >= 0; i--) {
System.out.print("Level " + i + " : ");
SkipListNode<String, String> cur = obj.head;
while (cur.nextNodes.get(i) != null) {
SkipListNode<String, String> next = cur.nextNodes.get(i);
System.out.print("(" + next.key + " , " + next.val + ") ");
cur = next;
}
System.out.println();
}
}
public static void main(String[] args) {
SkipListMap<String, String> test = new SkipListMap<>();
printAll(test);
System.out.println("======================");
test.put("A", "10");
printAll(test);
System.out.println("======================");
test.remove("A");
printAll(test);
System.out.println("======================");
test.put("E", "E");
test.put("B", "B");
test.put("A", "A");
test.put("F", "F");
test.put("C", "C");
test.put("D", "D");
printAll(test);
System.out.println("======================");
System.out.println(test.containsKey("B"));
System.out.println(test.containsKey("Z"));
System.out.println(test.firstKey());
System.out.println(test.lastKey());
System.out.println(test.floorKey("D"));
System.out.println(test.ceilingKey("D"));
System.out.println("======================");
test.remove("D");
printAll(test);
System.out.println("======================");
System.out.println(test.floorKey("D"));
System.out.println(test.ceilingKey("D"));
}
}

@ -0,0 +1,224 @@
package class37;
import java.util.HashSet;
public class Code01_CountofRangeSum {
public static int countRangeSum1(int[] nums, int lower, int upper) {
int n = nums.length;
long[] sums = new long[n + 1];
for (int i = 0; i < n; ++i)
sums[i + 1] = sums[i] + nums[i];
return countWhileMergeSort(sums, 0, n + 1, lower, upper);
}
private static int countWhileMergeSort(long[] sums, int start, int end, int lower, int upper) {
if (end - start <= 1)
return 0;
int mid = (start + end) / 2;
int count = countWhileMergeSort(sums, start, mid, lower, upper)
+ countWhileMergeSort(sums, mid, end, lower, upper);
int j = mid, k = mid, t = mid;
long[] cache = new long[end - start];
for (int i = start, r = 0; i < mid; ++i, ++r) {
while (k < end && sums[k] - sums[i] < lower)
k++;
while (j < end && sums[j] - sums[i] <= upper)
j++;
while (t < end && sums[t] < sums[i])
cache[r++] = sums[t++];
cache[r] = sums[i];
count += j - k;
}
System.arraycopy(cache, 0, sums, start, t - start);
return count;
}
public static class SBTNode {
public long key;
public SBTNode l;
public SBTNode r;
public long size; // 不同key的size
public long all; // 总的size
public SBTNode(long k) {
key = k;
size = 1;
all = 1;
}
}
public static class SizeBalancedTreeSet {
private SBTNode root;
private HashSet<Long> set = new HashSet<>();
private SBTNode rightRotate(SBTNode cur) {
long same = cur.all - (cur.l != null ? cur.l.all : 0) - (cur.r != null ? cur.r.all : 0);
SBTNode leftNode = cur.l;
cur.l = leftNode.r;
leftNode.r = cur;
leftNode.size = cur.size;
cur.size = (cur.l != null ? cur.l.size : 0) + (cur.r != null ? cur.r.size : 0) + 1;
// all modify
leftNode.all = cur.all;
cur.all = (cur.l != null ? cur.l.all : 0) + (cur.r != null ? cur.r.all : 0) + same;
return leftNode;
}
private SBTNode leftRotate(SBTNode cur) {
long same = cur.all - (cur.l != null ? cur.l.all : 0) - (cur.r != null ? cur.r.all : 0);
SBTNode rightNode = cur.r;
cur.r = rightNode.l;
rightNode.l = cur;
rightNode.size = cur.size;
cur.size = (cur.l != null ? cur.l.size : 0) + (cur.r != null ? cur.r.size : 0) + 1;
// all modify
rightNode.all = cur.all;
cur.all = (cur.l != null ? cur.l.all : 0) + (cur.r != null ? cur.r.all : 0) + same;
return rightNode;
}
private SBTNode maintain(SBTNode cur) {
if (cur == null) {
return null;
}
long leftSize = cur.l != null ? cur.l.size : 0;
long leftLeftSize = cur.l != null && cur.l.l != null ? cur.l.l.size : 0;
long leftRightSize = cur.l != null && cur.l.r != null ? cur.l.r.size : 0;
long rightSize = cur.r != null ? cur.r.size : 0;
long rightLeftSize = cur.r != null && cur.r.l != null ? cur.r.l.size : 0;
long rightRightSize = cur.r != null && cur.r.r != null ? cur.r.r.size : 0;
if (leftLeftSize > rightSize) {
cur = rightRotate(cur);
cur.r = maintain(cur.r);
cur = maintain(cur);
} else if (leftRightSize > rightSize) {
cur.l = leftRotate(cur.l);
cur = rightRotate(cur);
cur.l = maintain(cur.l);
cur.r = maintain(cur.r);
cur = maintain(cur);
} else if (rightRightSize > leftSize) {
cur = leftRotate(cur);
cur.l = maintain(cur.l);
cur = maintain(cur);
} else if (rightLeftSize > leftSize) {
cur.r = rightRotate(cur.r);
cur = leftRotate(cur);
cur.l = maintain(cur.l);
cur.r = maintain(cur.r);
cur = maintain(cur);
}
return cur;
}
private SBTNode add(SBTNode cur, long key, boolean contains) {
if (cur == null) {
return new SBTNode(key);
} else {
cur.all++;
if (key == cur.key) {
return cur;
} else { // 还在左滑或者右滑
if (!contains) {
cur.size++;
}
if (key < cur.key) {
cur.l = add(cur.l, key, contains);
} else {
cur.r = add(cur.r, key, contains);
}
return maintain(cur);
}
}
}
public void add(long sum) {
boolean contains = set.contains(sum);
root = add(root, sum, contains);
set.add(sum);
}
public long lessKeySize(long key) {
SBTNode cur = root;
long ans = 0;
while (cur != null) {
if (key == cur.key) {
return ans + (cur.l != null ? cur.l.all : 0);
} else if (key < cur.key) {
cur = cur.l;
} else {
ans += cur.all - (cur.r != null ? cur.r.all : 0);
cur = cur.r;
}
}
return ans;
}
// > 7 8...
// <8 ...<=7
public long moreKeySize(long key) {
return root != null ? (root.all - lessKeySize(key + 1)) : 0;
}
}
public static int countRangeSum2(int[] nums, int lower, int upper) {
SizeBalancedTreeSet treeSet = new SizeBalancedTreeSet();
long sum = 0;
int ans = 0;
treeSet.add(0);// 一个数都没有的时候就已经有一个前缀和累加和为0
for (int i = 0; i < nums.length; i++) {
sum += nums[i];
// sum i结尾的时候[lower, upper]
// 之前所有前缀累加和中,有多少累加和落在[sum - upper, sum - lower]
// 查 < sum - lower + 1 a
// 查 ? < sum - upper b
// a - b
long a = treeSet.lessKeySize(sum - lower + 1);
long b = treeSet.lessKeySize(sum - upper);
ans += a - b;
treeSet.add(sum);
}
return ans;
}
// for test
public static void printArray(int[] arr) {
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
// for test
public static int[] generateArray(int len, int varible) {
int[] arr = new int[len];
for (int i = 0; i < arr.length; i++) {
arr[i] = (int) (Math.random() * varible);
}
return arr;
}
public static void main(String[] args) {
int len = 200;
int varible = 50;
for (int i = 0; i < 10000; i++) {
int[] test = generateArray(len, varible);
int lower = (int) (Math.random() * varible) - (int) (Math.random() * varible);
int upper = lower + (int) (Math.random() * varible);
int ans1 = countRangeSum1(test, lower, upper);
int ans2 = countRangeSum2(test, lower, upper);
if (ans1 != ans2) {
printArray(test);
System.out.println(lower);
System.out.println(upper);
System.out.println(ans1);
System.out.println(ans2);
}
}
}
}

@ -0,0 +1,228 @@
package class37;
public class Code02_SlidingWindowMedian {
public static class SBTNode<K extends Comparable<K>> {
public K key;
public SBTNode<K> l;
public SBTNode<K> r;
public int size;
public SBTNode(K k) {
key = k;
size = 1;
}
}
public static class SizeBalancedTreeMap<K extends Comparable<K>> {
private SBTNode<K> root;
private SBTNode<K> rightRotate(SBTNode<K> cur) {
SBTNode<K> leftNode = cur.l;
cur.l = leftNode.r;
leftNode.r = cur;
leftNode.size = cur.size;
cur.size = (cur.l != null ? cur.l.size : 0) + (cur.r != null ? cur.r.size : 0) + 1;
return leftNode;
}
private SBTNode<K> leftRotate(SBTNode<K> cur) {
SBTNode<K> rightNode = cur.r;
cur.r = rightNode.l;
rightNode.l = cur;
rightNode.size = cur.size;
cur.size = (cur.l != null ? cur.l.size : 0) + (cur.r != null ? cur.r.size : 0) + 1;
return rightNode;
}
private SBTNode<K> maintain(SBTNode<K> cur) {
if (cur == null) {
return null;
}
int leftSize = cur.l != null ? cur.l.size : 0;
int leftLeftSize = cur.l != null && cur.l.l != null ? cur.l.l.size : 0;
int leftRightSize = cur.l != null && cur.l.r != null ? cur.l.r.size : 0;
int rightSize = cur.r != null ? cur.r.size : 0;
int rightLeftSize = cur.r != null && cur.r.l != null ? cur.r.l.size : 0;
int rightRightSize = cur.r != null && cur.r.r != null ? cur.r.r.size : 0;
if (leftLeftSize > rightSize) {
cur = rightRotate(cur);
cur.r = maintain(cur.r);
cur = maintain(cur);
} else if (leftRightSize > rightSize) {
cur.l = leftRotate(cur.l);
cur = rightRotate(cur);
cur.l = maintain(cur.l);
cur.r = maintain(cur.r);
cur = maintain(cur);
} else if (rightRightSize > leftSize) {
cur = leftRotate(cur);
cur.l = maintain(cur.l);
cur = maintain(cur);
} else if (rightLeftSize > leftSize) {
cur.r = rightRotate(cur.r);
cur = leftRotate(cur);
cur.l = maintain(cur.l);
cur.r = maintain(cur.r);
cur = maintain(cur);
}
return cur;
}
private SBTNode<K> findLastIndex(K key) {
SBTNode<K> pre = root;
SBTNode<K> cur = root;
while (cur != null) {
pre = cur;
if (key.compareTo(cur.key) == 0) {
break;
} else if (key.compareTo(cur.key) < 0) {
cur = cur.l;
} else {
cur = cur.r;
}
}
return pre;
}
private SBTNode<K> add(SBTNode<K> cur, K key) {
if (cur == null) {
return new SBTNode<K>(key);
} else {
cur.size++;
if (key.compareTo(cur.key) < 0) {
cur.l = add(cur.l, key);
} else {
cur.r = add(cur.r, key);
}
return maintain(cur);
}
}
private SBTNode<K> delete(SBTNode<K> cur, K key) {
cur.size--;
if (key.compareTo(cur.key) > 0) {
cur.r = delete(cur.r, key);
} else if (key.compareTo(cur.key) < 0) {
cur.l = delete(cur.l, key);
} else {
if (cur.l == null && cur.r == null) {
// free cur memory -> C++
cur = null;
} else if (cur.l == null && cur.r != null) {
// free cur memory -> C++
cur = cur.r;
} else if (cur.l != null && cur.r == null) {
// free cur memory -> C++
cur = cur.l;
} else {
SBTNode<K> pre = null;
SBTNode<K> des = cur.r;
des.size--;
while (des.l != null) {
pre = des;
des = des.l;
des.size--;
}
if (pre != null) {
pre.l = des.r;
des.r = cur.r;
}
des.l = cur.l;
des.size = des.l.size + (des.r == null ? 0 : des.r.size) + 1;
// free cur memory -> C++
cur = des;
}
}
return cur;
}
private SBTNode<K> getIndex(SBTNode<K> cur, int kth) {
if (kth == (cur.l != null ? cur.l.size : 0) + 1) {
return cur;
} else if (kth <= (cur.l != null ? cur.l.size : 0)) {
return getIndex(cur.l, kth);
} else {
return getIndex(cur.r, kth - (cur.l != null ? cur.l.size : 0) - 1);
}
}
public int size() {
return root == null ? 0 : root.size;
}
public boolean containsKey(K key) {
if (key == null) {
throw new RuntimeException("invalid parameter.");
}
SBTNode<K> lastNode = findLastIndex(key);
return lastNode != null && key.compareTo(lastNode.key) == 0 ? true : false;
}
public void add(K key) {
if (key == null) {
throw new RuntimeException("invalid parameter.");
}
SBTNode<K> lastNode = findLastIndex(key);
if (lastNode == null || key.compareTo(lastNode.key) != 0) {
root = add(root, key);
}
}
public void remove(K key) {
if (key == null) {
throw new RuntimeException("invalid parameter.");
}
if (containsKey(key)) {
root = delete(root, key);
}
}
public K getIndexKey(int index) {
if (index < 0 || index >= this.size()) {
throw new RuntimeException("invalid parameter.");
}
return getIndex(root, index + 1).key;
}
}
public static class Node implements Comparable<Node> {
public int index;
public int value;
public Node(int i, int v) {
index = i;
value = v;
}
@Override
public int compareTo(Node o) {
return value != o.value ? Integer.valueOf(value).compareTo(o.value)
: Integer.valueOf(index).compareTo(o.index);
}
}
public static double[] medianSlidingWindow(int[] nums, int k) {
SizeBalancedTreeMap<Node> map = new SizeBalancedTreeMap<>();
for (int i = 0; i < k - 1; i++) {
map.add(new Node(i, nums[i]));
}
double[] ans = new double[nums.length - k + 1];
int index = 0;
for (int i = k - 1; i < nums.length; i++) {
map.add(new Node(i, nums[i]));
if (map.size() % 2 == 0) {
Node upmid = map.getIndexKey(map.size() / 2 - 1);
Node downmid = map.getIndexKey(map.size() / 2);
ans[index++] = ((double) upmid.value + (double) downmid.value) / 2;
} else {
Node mid = map.getIndexKey(map.size() / 2);
ans[index++] = (double) mid.value;
}
map.remove(new Node(i - k + 1, nums[i - k + 1]));
}
return ans;
}
}

@ -0,0 +1,259 @@
package class37;
import java.util.ArrayList;
public class Code03_AddRemoveGetIndexGreat {
public static class SBTNode<V> {
public V value;
public SBTNode<V> l;
public SBTNode<V> r;
public int size;
public SBTNode(V v) {
value = v;
size = 1;
}
}
public static class SbtList<V> {
private SBTNode<V> root;
private SBTNode<V> rightRotate(SBTNode<V> cur) {
SBTNode<V> leftNode = cur.l;
cur.l = leftNode.r;
leftNode.r = cur;
leftNode.size = cur.size;
cur.size = (cur.l != null ? cur.l.size : 0) + (cur.r != null ? cur.r.size : 0) + 1;
return leftNode;
}
private SBTNode<V> leftRotate(SBTNode<V> cur) {
SBTNode<V> rightNode = cur.r;
cur.r = rightNode.l;
rightNode.l = cur;
rightNode.size = cur.size;
cur.size = (cur.l != null ? cur.l.size : 0) + (cur.r != null ? cur.r.size : 0) + 1;
return rightNode;
}
private SBTNode<V> maintain(SBTNode<V> cur) {
if (cur == null) {
return null;
}
int leftSize = cur.l != null ? cur.l.size : 0;
int leftLeftSize = cur.l != null && cur.l.l != null ? cur.l.l.size : 0;
int leftRightSize = cur.l != null && cur.l.r != null ? cur.l.r.size : 0;
int rightSize = cur.r != null ? cur.r.size : 0;
int rightLeftSize = cur.r != null && cur.r.l != null ? cur.r.l.size : 0;
int rightRightSize = cur.r != null && cur.r.r != null ? cur.r.r.size : 0;
if (leftLeftSize > rightSize) {
cur = rightRotate(cur);
cur.r = maintain(cur.r);
cur = maintain(cur);
} else if (leftRightSize > rightSize) {
cur.l = leftRotate(cur.l);
cur = rightRotate(cur);
cur.l = maintain(cur.l);
cur.r = maintain(cur.r);
cur = maintain(cur);
} else if (rightRightSize > leftSize) {
cur = leftRotate(cur);
cur.l = maintain(cur.l);
cur = maintain(cur);
} else if (rightLeftSize > leftSize) {
cur.r = rightRotate(cur.r);
cur = leftRotate(cur);
cur.l = maintain(cur.l);
cur.r = maintain(cur.r);
cur = maintain(cur);
}
return cur;
}
private SBTNode<V> add(SBTNode<V> root, int index, SBTNode<V> cur) {
if (root == null) {
return cur;
}
root.size++;
int leftAndHeadSize = (root.l != null ? root.l.size : 0) + 1;
if (index < leftAndHeadSize) {
root.l = add(root.l, index, cur);
} else {
root.r = add(root.r, index - leftAndHeadSize, cur);
}
root = maintain(root);
return root;
}
private SBTNode<V> remove(SBTNode<V> root, int index) {
root.size--;
int rootIndex = root.l != null ? root.l.size : 0;
if (index != rootIndex) {
if (index < rootIndex) {
root.l = remove(root.l, index);
} else {
root.r = remove(root.r, index - rootIndex - 1);
}
return root;
}
if (root.l == null && root.r == null) {
return null;
}
if (root.l == null) {
return root.r;
}
if (root.r == null) {
return root.l;
}
SBTNode<V> pre = null;
SBTNode<V> suc = root.r;
suc.size--;
while (suc.l != null) {
pre = suc;
suc = suc.l;
suc.size--;
}
if (pre != null) {
pre.l = suc.r;
suc.r = root.r;
}
suc.l = root.l;
suc.size = suc.l.size + (suc.r == null ? 0 : suc.r.size) + 1;
return suc;
}
private SBTNode<V> get(SBTNode<V> root, int index) {
int leftSize = root.l != null ? root.l.size : 0;
if (index < leftSize) {
return get(root.l, index);
} else if (index == leftSize) {
return root;
} else {
return get(root.r, index - leftSize - 1);
}
}
public void add(int index, V num) {
SBTNode<V> cur = new SBTNode<V>(num);
if (root == null) {
root = cur;
} else {
if (index <= root.size) {
root = add(root, index, cur);
}
}
}
public V get(int index) {
SBTNode<V> ans = get(root, index);
return ans.value;
}
public void remove(int index) {
if (index >= 0 && size() > index) {
root = remove(root, index);
}
}
public int size() {
return root == null ? 0 : root.size;
}
}
// 通过以下这个测试,
// 可以很明显的看到LinkedList的插入、删除、get效率不如SbtList
// LinkedList需要找到index所在的位置之后才能插入或者读取时间复杂度O(N)
// SbtList是平衡搜索二叉树所以插入或者读取时间复杂度都是O(logN)
public static void main(String[] args) {
// 功能测试
int test = 50000;
int max = 1000000;
boolean pass = true;
ArrayList<Integer> list = new ArrayList<>();
SbtList<Integer> sbtList = new SbtList<>();
for (int i = 0; i < test; i++) {
if (list.size() != sbtList.size()) {
pass = false;
break;
}
if (list.size() > 1 && Math.random() < 0.5) {
int removeIndex = (int) (Math.random() * list.size());
list.remove(removeIndex);
sbtList.remove(removeIndex);
} else {
int randomIndex = (int) (Math.random() * (list.size() + 1));
int randomValue = (int) (Math.random() * (max + 1));
list.add(randomIndex, randomValue);
sbtList.add(randomIndex, randomValue);
}
}
for (int i = 0; i < list.size(); i++) {
if (!list.get(i).equals(sbtList.get(i))) {
pass = false;
break;
}
}
System.out.println("功能测试是否通过 : " + pass);
// 性能测试
test = 500000;
list = new ArrayList<>();
sbtList = new SbtList<>();
long start = 0;
long end = 0;
start = System.currentTimeMillis();
for (int i = 0; i < test; i++) {
int randomIndex = (int) (Math.random() * (list.size() + 1));
int randomValue = (int) (Math.random() * (max + 1));
list.add(randomIndex, randomValue);
}
end = System.currentTimeMillis();
System.out.println("ArrayList插入总时长(毫秒) " + (end - start));
start = System.currentTimeMillis();
for (int i = 0; i < test; i++) {
int randomIndex = (int) (Math.random() * (i + 1));
list.get(randomIndex);
}
end = System.currentTimeMillis();
System.out.println("ArrayList读取总时长(毫秒) : " + (end - start));
start = System.currentTimeMillis();
for (int i = 0; i < test; i++) {
int randomIndex = (int) (Math.random() * list.size());
list.remove(randomIndex);
}
end = System.currentTimeMillis();
System.out.println("ArrayList删除总时长(毫秒) : " + (end - start));
start = System.currentTimeMillis();
for (int i = 0; i < test; i++) {
int randomIndex = (int) (Math.random() * (sbtList.size() + 1));
int randomValue = (int) (Math.random() * (max + 1));
sbtList.add(randomIndex, randomValue);
}
end = System.currentTimeMillis();
System.out.println("SbtList插入总时长(毫秒) : " + (end - start));
start = System.currentTimeMillis();
for (int i = 0; i < test; i++) {
int randomIndex = (int) (Math.random() * (i + 1));
sbtList.get(randomIndex);
}
end = System.currentTimeMillis();
System.out.println("SbtList读取总时长(毫秒) : " + (end - start));
start = System.currentTimeMillis();
for (int i = 0; i < test; i++) {
int randomIndex = (int) (Math.random() * sbtList.size());
sbtList.remove(randomIndex);
}
end = System.currentTimeMillis();
System.out.println("SbtList删除总时长(毫秒) : " + (end - start));
}
}

@ -0,0 +1,408 @@
package class37;
import java.util.TreeMap;
import class35.Code01_AVLTreeMap.AVLTreeMap;
import class36.Code01_SizeBalancedTreeMap.SizeBalancedTreeMap;
import class36.Code02_SkipListMap.SkipListMap;
// 本文件为avl、sbt、skiplist三种结构的测试文件
public class Compare {
public static void functionTest() {
System.out.println("功能测试开始");
TreeMap<Integer, Integer> treeMap = new TreeMap<>();
AVLTreeMap<Integer, Integer> avl = new AVLTreeMap<>();
SizeBalancedTreeMap<Integer, Integer> sbt = new SizeBalancedTreeMap<>();
SkipListMap<Integer, Integer> skip = new SkipListMap<>();
int maxK = 500;
int maxV = 50000;
int testTime = 1000000;
for (int i = 0; i < testTime; i++) {
int addK = (int) (Math.random() * maxK);
int addV = (int) (Math.random() * maxV);
treeMap.put(addK, addV);
avl.put(addK, addV);
sbt.put(addK, addV);
skip.put(addK, addV);
int removeK = (int) (Math.random() * maxK);
treeMap.remove(removeK);
avl.remove(removeK);
sbt.remove(removeK);
skip.remove(removeK);
int querryK = (int) (Math.random() * maxK);
if (treeMap.containsKey(querryK) != avl.containsKey(querryK)
|| sbt.containsKey(querryK) != skip.containsKey(querryK)
|| treeMap.containsKey(querryK) != sbt.containsKey(querryK)) {
System.out.println("containsKey Oops");
System.out.println(treeMap.containsKey(querryK));
System.out.println(avl.containsKey(querryK));
System.out.println(sbt.containsKey(querryK));
System.out.println(skip.containsKey(querryK));
break;
}
if (treeMap.containsKey(querryK)) {
int v1 = treeMap.get(querryK);
int v2 = avl.get(querryK);
int v3 = sbt.get(querryK);
int v4 = skip.get(querryK);
if (v1 != v2 || v3 != v4 || v1 != v3) {
System.out.println("get Oops");
System.out.println(treeMap.get(querryK));
System.out.println(avl.get(querryK));
System.out.println(sbt.get(querryK));
System.out.println(skip.get(querryK));
break;
}
Integer f1 = treeMap.floorKey(querryK);
Integer f2 = avl.floorKey(querryK);
Integer f3 = sbt.floorKey(querryK);
Integer f4 = skip.floorKey(querryK);
if (f1 == null && (f2 != null || f3 != null || f4 != null)) {
System.out.println("floorKey Oops");
System.out.println(treeMap.floorKey(querryK));
System.out.println(avl.floorKey(querryK));
System.out.println(sbt.floorKey(querryK));
System.out.println(skip.floorKey(querryK));
break;
}
if (f1 != null && (f2 == null || f3 == null || f4 == null)) {
System.out.println("floorKey Oops");
System.out.println(treeMap.floorKey(querryK));
System.out.println(avl.floorKey(querryK));
System.out.println(sbt.floorKey(querryK));
System.out.println(skip.floorKey(querryK));
break;
}
if (f1 != null) {
int ans1 = f1;
int ans2 = f2;
int ans3 = f3;
int ans4 = f4;
if (ans1 != ans2 || ans3 != ans4 || ans1 != ans3) {
System.out.println("floorKey Oops");
System.out.println(treeMap.floorKey(querryK));
System.out.println(avl.floorKey(querryK));
System.out.println(sbt.floorKey(querryK));
System.out.println(skip.floorKey(querryK));
break;
}
}
f1 = treeMap.ceilingKey(querryK);
f2 = avl.ceilingKey(querryK);
f3 = sbt.ceilingKey(querryK);
f4 = skip.ceilingKey(querryK);
if (f1 == null && (f2 != null || f3 != null || f4 != null)) {
System.out.println("ceilingKey Oops");
System.out.println(treeMap.ceilingKey(querryK));
System.out.println(avl.ceilingKey(querryK));
System.out.println(sbt.ceilingKey(querryK));
System.out.println(skip.ceilingKey(querryK));
break;
}
if (f1 != null && (f2 == null || f3 == null || f4 == null)) {
System.out.println("ceilingKey Oops");
System.out.println(treeMap.ceilingKey(querryK));
System.out.println(avl.ceilingKey(querryK));
System.out.println(sbt.ceilingKey(querryK));
System.out.println(skip.ceilingKey(querryK));
break;
}
if (f1 != null) {
int ans1 = f1;
int ans2 = f2;
int ans3 = f3;
int ans4 = f4;
if (ans1 != ans2 || ans3 != ans4 || ans1 != ans3) {
System.out.println("ceilingKey Oops");
System.out.println(treeMap.ceilingKey(querryK));
System.out.println(avl.ceilingKey(querryK));
System.out.println(sbt.ceilingKey(querryK));
System.out.println(skip.ceilingKey(querryK));
break;
}
}
}
Integer f1 = treeMap.firstKey();
Integer f2 = avl.firstKey();
Integer f3 = sbt.firstKey();
Integer f4 = skip.firstKey();
if (f1 == null && (f2 != null || f3 != null || f4 != null)) {
System.out.println("firstKey Oops");
System.out.println(treeMap.firstKey());
System.out.println(avl.firstKey());
System.out.println(sbt.firstKey());
System.out.println(skip.firstKey());
break;
}
if (f1 != null && (f2 == null || f3 == null || f4 == null)) {
System.out.println("firstKey Oops");
System.out.println(treeMap.firstKey());
System.out.println(avl.firstKey());
System.out.println(sbt.firstKey());
System.out.println(skip.firstKey());
break;
}
if (f1 != null) {
int ans1 = f1;
int ans2 = f2;
int ans3 = f3;
int ans4 = f4;
if (ans1 != ans2 || ans3 != ans4 || ans1 != ans3) {
System.out.println("firstKey Oops");
System.out.println(treeMap.firstKey());
System.out.println(avl.firstKey());
System.out.println(sbt.firstKey());
System.out.println(skip.firstKey());
break;
}
}
f1 = treeMap.lastKey();
f2 = avl.lastKey();
f3 = sbt.lastKey();
f4 = skip.lastKey();
if (f1 == null && (f2 != null || f3 != null || f4 != null)) {
System.out.println("lastKey Oops");
System.out.println(treeMap.lastKey());
System.out.println(avl.lastKey());
System.out.println(sbt.lastKey());
System.out.println(skip.lastKey());
break;
}
if (f1 != null && (f2 == null || f3 == null || f4 == null)) {
System.out.println("firstKey Oops");
System.out.println(treeMap.lastKey());
System.out.println(avl.lastKey());
System.out.println(sbt.lastKey());
System.out.println(skip.lastKey());
break;
}
if (f1 != null) {
int ans1 = f1;
int ans2 = f2;
int ans3 = f3;
int ans4 = f4;
if (ans1 != ans2 || ans3 != ans4 || ans1 != ans3) {
System.out.println("lastKey Oops");
System.out.println(treeMap.lastKey());
System.out.println(avl.lastKey());
System.out.println(sbt.lastKey());
System.out.println(skip.lastKey());
break;
}
}
if (treeMap.size() != avl.size() || sbt.size() != skip.size() || treeMap.size() != sbt.size()) {
System.out.println("size Oops");
System.out.println(treeMap.size());
System.out.println(avl.size());
System.out.println(sbt.size());
System.out.println(skip.size());
break;
}
}
System.out.println("功能测试结束");
}
public static void performanceTest() {
System.out.println("性能测试开始");
TreeMap<Integer, Integer> treeMap;
AVLTreeMap<Integer, Integer> avl;
SizeBalancedTreeMap<Integer, Integer> sbt;
SkipListMap<Integer, Integer> skip;
long start;
long end;
int max = 1000000;
treeMap = new TreeMap<>();
avl = new AVLTreeMap<>();
sbt = new SizeBalancedTreeMap<>();
skip = new SkipListMap<>();
System.out.println("顺序递增加入测试,数据规模 : " + max);
start = System.currentTimeMillis();
for (int i = 0; i < max; i++) {
treeMap.put(i, i);
}
end = System.currentTimeMillis();
System.out.println("treeMap 运行时间 : " + (end - start) + "ms");
start = System.currentTimeMillis();
for (int i = 0; i < max; i++) {
avl.put(i, i);
}
end = System.currentTimeMillis();
System.out.println("avl 运行时间 : " + (end - start) + "ms");
start = System.currentTimeMillis();
for (int i = 0; i < max; i++) {
sbt.put(i, i);
}
end = System.currentTimeMillis();
System.out.println("sbt 运行时间 : " + (end - start) + "ms");
start = System.currentTimeMillis();
for (int i = 0; i < max; i++) {
skip.put(i, i);
}
end = System.currentTimeMillis();
System.out.println("skip 运行时间 : " + (end - start) + "ms");
System.out.println("顺序递增删除测试,数据规模 : " + max);
start = System.currentTimeMillis();
for (int i = 0; i < max; i++) {
treeMap.remove(i);
}
end = System.currentTimeMillis();
System.out.println("treeMap 运行时间 : " + (end - start) + "ms");
start = System.currentTimeMillis();
for (int i = 0; i < max; i++) {
avl.remove(i);
}
end = System.currentTimeMillis();
System.out.println("avl 运行时间 : " + (end - start) + "ms");
start = System.currentTimeMillis();
for (int i = 0; i < max; i++) {
sbt.remove(i);
}
end = System.currentTimeMillis();
System.out.println("sbt 运行时间 : " + (end - start) + "ms");
start = System.currentTimeMillis();
for (int i = 0; i < max; i++) {
skip.remove(i);
}
end = System.currentTimeMillis();
System.out.println("skip 运行时间 : " + (end - start) + "ms");
System.out.println("顺序递减加入测试,数据规模 : " + max);
start = System.currentTimeMillis();
for (int i = max; i >= 0; i--) {
treeMap.put(i, i);
}
end = System.currentTimeMillis();
System.out.println("treeMap 运行时间 : " + (end - start) + "ms");
start = System.currentTimeMillis();
for (int i = max; i >= 0; i--) {
avl.put(i, i);
}
end = System.currentTimeMillis();
System.out.println("avl 运行时间 : " + (end - start) + "ms");
start = System.currentTimeMillis();
for (int i = max; i >= 0; i--) {
sbt.put(i, i);
}
end = System.currentTimeMillis();
System.out.println("sbt 运行时间 : " + (end - start) + "ms");
start = System.currentTimeMillis();
for (int i = max; i >= 0; i--) {
skip.put(i, i);
}
end = System.currentTimeMillis();
System.out.println("skip 运行时间 : " + (end - start) + "ms");
System.out.println("顺序递减删除测试,数据规模 : " + max);
start = System.currentTimeMillis();
for (int i = max; i >= 0; i--) {
treeMap.remove(i);
}
end = System.currentTimeMillis();
System.out.println("treeMap 运行时间 : " + (end - start) + "ms");
start = System.currentTimeMillis();
for (int i = max; i >= 0; i--) {
avl.remove(i);
}
end = System.currentTimeMillis();
System.out.println("avl 运行时间 : " + (end - start) + "ms");
start = System.currentTimeMillis();
for (int i = max; i >= 0; i--) {
sbt.remove(i);
}
end = System.currentTimeMillis();
System.out.println("sbt 运行时间 : " + (end - start) + "ms");
start = System.currentTimeMillis();
for (int i = max; i >= 0; i--) {
skip.remove(i);
}
end = System.currentTimeMillis();
System.out.println("skip 运行时间 : " + (end - start) + "ms");
System.out.println("随机加入测试,数据规模 : " + max);
start = System.currentTimeMillis();
for (int i = 0; i < max; i++) {
treeMap.put((int) (Math.random() * i), i);
}
end = System.currentTimeMillis();
System.out.println("treeMap 运行时间 : " + (end - start) + "ms");
start = System.currentTimeMillis();
for (int i = max; i >= 0; i--) {
avl.put((int) (Math.random() * i), i);
}
end = System.currentTimeMillis();
System.out.println("avl 运行时间 : " + (end - start) + "ms");
start = System.currentTimeMillis();
for (int i = max; i >= 0; i--) {
sbt.put((int) (Math.random() * i), i);
}
end = System.currentTimeMillis();
System.out.println("sbt 运行时间 : " + (end - start) + "ms");
start = System.currentTimeMillis();
for (int i = max; i >= 0; i--) {
skip.put((int) (Math.random() * i), i);
}
end = System.currentTimeMillis();
System.out.println("skip 运行时间 : " + (end - start) + "ms");
System.out.println("随机删除测试,数据规模 : " + max);
start = System.currentTimeMillis();
for (int i = 0; i < max; i++) {
treeMap.remove((int) (Math.random() * i));
}
end = System.currentTimeMillis();
System.out.println("treeMap 运行时间 : " + (end - start) + "ms");
start = System.currentTimeMillis();
for (int i = max; i >= 0; i--) {
avl.remove((int) (Math.random() * i));
}
end = System.currentTimeMillis();
System.out.println("avl 运行时间 : " + (end - start) + "ms");
start = System.currentTimeMillis();
for (int i = max; i >= 0; i--) {
sbt.remove((int) (Math.random() * i));
}
end = System.currentTimeMillis();
System.out.println("sbt 运行时间 : " + (end - start) + "ms");
start = System.currentTimeMillis();
for (int i = max; i >= 0; i--) {
skip.remove((int) (Math.random() * i));
}
end = System.currentTimeMillis();
System.out.println("skip 运行时间 : " + (end - start) + "ms");
System.out.println("性能测试结束");
}
public static void main(String[] args) {
functionTest();
System.out.println("======");
performanceTest();
}
}
Loading…
Cancel
Save