增加淘宝群内容,修改部分文件组织

此提交包含在:
2021-10-13 17:26:45 +08:00
父節點 142168ae8e
當前提交 4152e12576
共有 646 個檔案被更改,包括 62259 行新增0 行删除

查看文件

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="output" path="bin"/>
</classpath>

查看文件

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>11-哈希表</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

查看文件

@@ -0,0 +1,11 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.8

查看文件

@@ -0,0 +1,11 @@
package com.mj;
public class Asserts {
public static void test(boolean value) {
try {
if (!value) throw new Exception("测试未通过");
} catch (Exception e) {
e.printStackTrace();
}
}
}

查看文件

@@ -0,0 +1,259 @@
package com.mj;
import com.mj.Times.Task;
import com.mj.file.FileInfo;
import com.mj.file.Files;
import com.mj.map.HashMap;
import com.mj.map.Map;
import com.mj.map.Map.Visitor;
import com.mj.model.Key;
import com.mj.model.Person;
import com.mj.model.SubKey1;
import com.mj.model.SubKey2;
public class Main {
// static void test1() {
// String string = "jack"; // 3254239
// System.out.println(string.hashCode());
//// int len = string.length();
//// int hashCode = 0;
//// for (int i = 0; i < len; i++) {
//// char c = string.charAt(i);
//// hashCode = hashCode * 31 + c;
//// // hashCode = (hashCode << 5) - hashCode + c;
//// }
//// System.out.println(hashCode);
// // hashCode = ((j * 31 + a) * 31 + c) * 31 + k
// }
//
// static void test2() {
// Integer a = 110;
// Float b = 10.6f;
// Long c = 156l;
// Double d = 10.9;
// String e = "rose";
//
// System.out.println(a.hashCode());
// System.out.println(b.hashCode());
// System.out.println(c.hashCode());
// System.out.println(d.hashCode());
// System.out.println(e.hashCode());
// }
//
// static void test3() {
// Person p1 = new Person(10, 1.67f, "jack");
// Person p2 = new Person(10, 1.67f, "jack");
//
// Map<Object, Object> map = new HashMap<>();
// map.put(p1, "abc");
// map.put("test", "ccc");
// map.put(p2, "bcd");
// System.out.println(map.size());
// }
//
// static void test4() {
// Person p1 = new Person(10, 1.67f, "jack");
// Person p2 = new Person(10, 1.67f, "jack");
//
// Map<Object, Integer> map = new HashMap<>();
// map.put(p1, 1);
// map.put(p2, 2);
// map.put("jack", 3);
// map.put("rose", 4);
// map.put("jack", 5);
// map.put(null, 6);
//
//// System.out.println(map.size());
//// System.out.println(map.remove("jack"));
//// System.out.println(map.get("jack"));
//// System.out.println(map.size());
//
// System.out.println(map.containsKey(p1));
// System.out.println(map.containsKey(null));
// System.out.println(map.containsValue(6));
// System.out.println(map.containsValue(1));
//
//// map.traversal(new Visitor<Object, Integer>() {
//// public boolean visit(Object key, Integer value) {
//// System.out.println(key + "_" + value);
//// return false;
//// }
//// });
//
//// System.out.println(map.get("jack"));
//// System.out.println(map.get("rose"));
//// System.out.println(map.get(null));
//// System.out.println(map.get(p1));
// }
//
// static void test5() {
// Person p1 = new Person(10, 1.67f, "jack");
// Person p2 = new Person(10, 1.67f, "jack");
//
// Map<Object, Integer> map = new HashMap<>();
// map.put(p1, 1);
// map.put(p2, 2);
// map.put("jack", 3);
// map.put("rose", 4);
// map.put("jack", 5);
// map.put(null, 6);
//
//// System.out.println(map.size());
//// System.out.println(map.remove("jack"));
//// System.out.println(map.get("jack"));
//// System.out.println(map.size());
//
// System.out.println(map.containsKey(p1));
// System.out.println(map.containsKey(null));
// System.out.println(map.containsValue(6));
// System.out.println(map.containsValue(1));
//
//// map.traversal(new Visitor<Object, Integer>() {
//// public boolean visit(Object key, Integer value) {
//// System.out.println(key + "_" + value);
//// return false;
//// }
//// });
//
//// System.out.println(map.get("jack"));
//// System.out.println(map.get("rose"));
//// System.out.println(map.get(null));
//// System.out.println(map.get(p1));
// }
//
// static void test6() {
// HashMap<Object, Integer> map = new HashMap<>();
// for (int i = 1; i <= 19; i++) {
// map.put(new Key(i), i);
// }
//
// map.put(new Key(4), 100);
// Asserts.test(map.size() == 19);
// Asserts.test(map.get(new Key(4)) == 100);
// Asserts.test(map.get(new Key(18)) == 18);
// }
//
static void test2(HashMap<Object, Integer> map) {
for (int i = 1; i <= 20; i++) {
map.put(new Key(i), i);
}
for (int i = 5; i <= 7; i++) {
map.put(new Key(i), i + 5);
}
Asserts.test(map.size() == 20);
Asserts.test(map.get(new Key(4)) == 4);
Asserts.test(map.get(new Key(5)) == 10);
Asserts.test(map.get(new Key(6)) == 11);
Asserts.test(map.get(new Key(7)) == 12);
Asserts.test(map.get(new Key(8)) == 8);
}
static void test3(HashMap<Object, Integer> map) {
map.put(null, 1); // 1
map.put(new Object(), 2); // 2
map.put("jack", 3); // 3
map.put(10, 4); // 4
map.put(new Object(), 5); // 5
map.put("jack", 6);
map.put(10, 7);
map.put(null, 8);
map.put(10, null);
Asserts.test(map.size() == 5);
Asserts.test(map.get(null) == 8);
Asserts.test(map.get("jack") == 6);
Asserts.test(map.get(10) == null);
Asserts.test(map.get(new Object()) == null);
Asserts.test(map.containsKey(10));
Asserts.test(map.containsKey(null));
Asserts.test(map.containsValue(null));
Asserts.test(map.containsValue(1) == false);
}
static void test4(HashMap<Object, Integer> map) {
map.put("jack", 1);
map.put("rose", 2);
map.put("jim", 3);
map.put("jake", 4);
for (int i = 1; i <= 10; i++) {
map.put("test" + i, i);
map.put(new Key(i), i);
}
for (int i = 5; i <= 7; i++) {
Asserts.test(map.remove(new Key(i)) == i);
}
for (int i = 1; i <= 3; i++) {
map.put(new Key(i), i + 5);
}
Asserts.test(map.size() == 21);
Asserts.test(map.get(new Key(1)) == 6);
Asserts.test(map.get(new Key(2)) == 7);
Asserts.test(map.get(new Key(3)) == 8);
Asserts.test(map.get(new Key(4)) == 4);
Asserts.test(map.get(new Key(5)) == null);
Asserts.test(map.get(new Key(6)) == null);
Asserts.test(map.get(new Key(7)) == null);
Asserts.test(map.get(new Key(8)) == 8);
}
static void test5(HashMap<Object, Integer> map) {
for (int i = 1; i <= 20; i++) {
map.put(new SubKey1(i), i);
}
map.put(new SubKey2(1), 5);
Asserts.test(map.get(new SubKey1(1)) == 5);
Asserts.test(map.get(new SubKey2(1)) == 5);
Asserts.test(map.size() == 20);
}
static void test1() {
String filepath = "C:\\Users\\MJ Lee\\Desktop\\src\\java\\util";
FileInfo fileInfo = Files.read(filepath, null);
String[] words = fileInfo.words();
System.out.println("总行数:" + fileInfo.getLines());
System.out.println("单词总数:" + words.length);
System.out.println("-------------------------------------");
// java.util.HashMap<String, Integer> map = new java.util.HashMap<>();
//
// for (String word : words) {
// Integer count = map.get(word);
// count = count == null ? 0 : count;
// map.put(word, count + 1);
// }
// System.out.println(map.size()); // 17188
HashMap<String, Integer> map = new HashMap<>();
Times.test(map.getClass().getName(), new Task() {
@Override
public void execute() {
for (String word : words) {
Integer count = map.get(word);
count = count == null ? 0 : count;
map.put(word, count + 1);
}
System.out.println(map.size()); // 17188
int count = 0;
for (String word : words) {
Integer i = map.get(word);
count += i == null ? 0 : i;
map.remove(word);
}
Asserts.test(count == words.length);
Asserts.test(map.size() == 0);
}
});
}
public static void main(String[] args) {
test1();
test2(new HashMap<>());
test3(new HashMap<>());
test4(new HashMap<>());
test5(new HashMap<>());
}
}

查看文件

@@ -0,0 +1,26 @@
package com.mj;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Times {
private static final SimpleDateFormat fmt = new SimpleDateFormat("HH:mm:ss.SSS");
public interface Task {
void execute();
}
public static void test(String title, Task task) {
if (task == null) return;
title = (title == null) ? "" : ("" + title + "");
System.out.println(title);
System.out.println("开始:" + fmt.format(new Date()));
long begin = System.currentTimeMillis();
task.execute();
long end = System.currentTimeMillis();
System.out.println("结束:" + fmt.format(new Date()));
double delta = (end - begin) / 1000.0;
System.out.println("耗时:" + delta + "");
System.out.println("-------------------------------------");
}
}

查看文件

@@ -0,0 +1,47 @@
package com.mj.file;
public class FileInfo {
private int lines;
private int files;
private String content = "";
public String[] words() {
return content.split("[^a-zA-Z]+");
}
public int getFiles() {
return files;
}
public void setFiles(int files) {
this.files = files;
}
public int getLines() {
return lines;
}
public void setLines(int lines) {
this.lines = lines;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public FileInfo append(FileInfo info) {
if (info != null && info.lines > 0) {
this.files += info.files;
this.lines += info.lines;
this.content = new StringBuilder(this.content)
.append("\n")
.append(info.content)
.toString();
}
return this;
}
}

查看文件

@@ -0,0 +1,72 @@
package com.mj.file;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileFilter;
import java.io.FileReader;
import java.io.IOException;
public class Files {
/**
* 读取文件内容
* @param file
* @return
*/
public static FileInfo read(String file) {
if (file == null) return null;
FileInfo info = new FileInfo();
StringBuilder sb = new StringBuilder();
try (FileReader reader = new FileReader(file);
BufferedReader br = new BufferedReader(reader)) {
String line;
while ((line = br.readLine()) != null) {
sb.append(line).append("\n");
info.setLines(info.getLines() + 1);
}
int len = sb.length();
if (len > 0) {
sb.deleteCharAt(len - 1);
}
} catch (IOException e) {
e.printStackTrace();
}
info.setFiles(info.getFiles() + 1);
info.setContent(sb.toString());
return info;
}
/**
* 读取文件夹下面的文件内容
* @param dir
* @param extensions
* @return
*/
public static FileInfo read(String dir, String[] extensions) {
if (dir == null) return null;
File dirFile = new File(dir);
if (!dirFile.exists()) return null;
FileInfo info = new FileInfo();
dirFile.listFiles(new FileFilter() {
public boolean accept(File subFile) {
String subFilepath = subFile.getAbsolutePath();
if (subFile.isDirectory()) {
info.append(read(subFilepath, extensions));
} else if (extensions != null && extensions.length > 0) {
for (String extension : extensions) {
if (subFilepath.endsWith("." + extension)) {
info.append(read(subFilepath));
break;
}
}
} else {
info.append(read(subFilepath));
}
return false;
}
});
return info;
}
}

查看文件

@@ -0,0 +1,594 @@
package com.mj.map;
import java.util.LinkedList;
import java.util.Objects;
import java.util.Queue;
import org.w3c.dom.ls.LSException;
import com.mj.printer.BinaryTreeInfo;
import com.mj.printer.BinaryTrees;
@SuppressWarnings({"unchecked", "rawtypes"})
public class HashMap<K, V> implements Map<K, V> {
private static final boolean RED = false;
private static final boolean BLACK = true;
private int size;
private Node<K, V>[] table;
private static final int DEFAULT_CAPACITY = 1 << 4;
public HashMap() {
table = new Node[DEFAULT_CAPACITY];
}
@Override
public int size() {
return size;
}
@Override
public boolean isEmpty() {
return size == 0;
}
@Override
public void clear() {
if (size == 0) return;
size = 0;
for (int i = 0; i < table.length; i++) {
table[i] = null;
}
}
@Override
public V put(K key, V value) {
int index = index(key);
// 取出index位置的红黑树根节点
Node<K, V> root = table[index];
if (root == null) {
root = new Node<>(key, value, null);
table[index] = root;
size++;
afterPut(root);
return null;
}
// 添加新的节点到红黑树上面
Node<K, V> parent = root;
Node<K, V> node = root;
int cmp = 0;
K k1 = key;
int h1 = k1 == null ? 0 : k1.hashCode();
Node<K, V> result = null;
boolean searched = false; // 是否已经搜索过这个key
do {
parent = node;
K k2 = node.key;
int h2 = node.hash;
if (h1 > h2) {
cmp = 1;
} else if (h1 < h2) {
cmp = -1;
} else if (Objects.equals(k1, k2)) {
cmp = 0;
} else if (k1 != null && k2 != null
&& k1.getClass() == k2.getClass()
&& k1 instanceof Comparable
&& (cmp = ((Comparable) k1).compareTo(k2)) != 0) {
} else if (searched) { // 已经扫描了
cmp = System.identityHashCode(k1) - System.identityHashCode(k2);
} else { // searched == false; 还没有扫描,然后再根据内存地址大小决定左右
if ((node.left != null && (result = node(node.left, k1)) != null)
|| (node.right != null && (result = node(node.right, k1)) != null)) {
// 已经存在这个key
node = result;
cmp = 0;
} else { // 不存在这个key
searched = true;
cmp = System.identityHashCode(k1) - System.identityHashCode(k2);
}
}
if (cmp > 0) {
node = node.right;
} else if (cmp < 0) {
node = node.left;
} else { // 相等
V oldValue = node.value;
node.key = key;
node.value = value;
return oldValue;
}
} while (node != null);
// 看看插入到父节点的哪个位置
Node<K, V> newNode = new Node<>(key, value, parent);
if (cmp > 0) {
parent.right = newNode;
} else {
parent.left = newNode;
}
size++;
// 新添加节点之后的处理
afterPut(newNode);
return null;
}
@Override
public V get(K key) {
Node<K, V> node = node(key);
return node != null ? node.value : null;
}
@Override
public V remove(K key) {
return remove(node(key));
}
@Override
public boolean containsKey(K key) {
return node(key) != null;
}
@Override
public boolean containsValue(V value) {
if (size == 0) return false;
Queue<Node<K, V>> queue = new LinkedList<>();
for (int i = 0; i < table.length; i++) {
if (table[i] == null) continue;
queue.offer(table[i]);
while (!queue.isEmpty()) {
Node<K, V> node = queue.poll();
if (Objects.equals(value, node.value)) return true;
if (node.left != null) {
queue.offer(node.left);
}
if (node.right != null) {
queue.offer(node.right);
}
}
}
return false;
}
@Override
public void traversal(Visitor<K, V> visitor) {
if (size == 0 || visitor == null) return;
Queue<Node<K, V>> queue = new LinkedList<>();
for (int i = 0; i < table.length; i++) {
if (table[i] == null) continue;
queue.offer(table[i]);
while (!queue.isEmpty()) {
Node<K, V> node = queue.poll();
if (visitor.visit(node.key, node.value)) return;
if (node.left != null) {
queue.offer(node.left);
}
if (node.right != null) {
queue.offer(node.right);
}
}
}
}
public void print() {
if (size == 0) return;
for (int i = 0; i < table.length; i++) {
final Node<K, V> root = table[i];
System.out.println("【index = " + i + "");
BinaryTrees.println(new BinaryTreeInfo() {
@Override
public Object string(Object node) {
return node;
}
@Override
public Object root() {
return root;
}
@Override
public Object right(Object node) {
return ((Node<K, V>)node).right;
}
@Override
public Object left(Object node) {
return ((Node<K, V>)node).left;
}
});
System.out.println("---------------------------------------------------");
}
}
private V remove(Node<K, V> node) {
if (node == null) return null;
size--;
V oldValue = node.value;
if (node.hasTwoChildren()) { // 度为2的节点
// 找到后继节点
Node<K, V> s = successor(node);
// 用后继节点的值覆盖度为2的节点的值
node.key = s.key;
node.value = s.value;
// 删除后继节点
node = s;
}
// 删除node节点(node的度必然是1或者0)
Node<K, V> replacement = node.left != null ? node.left : node.right;
int index = index(node);
if (replacement != null) { // node是度为1的节点
// 更改parent
replacement.parent = node.parent;
// 更改parent的left、right的指向
if (node.parent == null) { // node是度为1的节点并且是根节点
table[index] = replacement;
} else if (node == node.parent.left) {
node.parent.left = replacement;
} else { // node == node.parent.right
node.parent.right = replacement;
}
// 删除节点之后的处理
afterRemove(replacement);
} else if (node.parent == null) { // node是叶子节点并且是根节点
table[index] = null;
} else { // node是叶子节点,但不是根节点
if (node == node.parent.left) {
node.parent.left = null;
} else { // node == node.parent.right
node.parent.right = null;
}
// 删除节点之后的处理
afterRemove(node);
}
return oldValue;
}
private Node<K, V> successor(Node<K, V> node) {
if (node == null) return null;
// 前驱节点在左子树当中(right.left.left.left....)
Node<K, V> p = node.right;
if (p != null) {
while (p.left != null) {
p = p.left;
}
return p;
}
// 从父节点、祖父节点中寻找前驱节点
while (node.parent != null && node == node.parent.right) {
node = node.parent;
}
return node.parent;
}
private Node<K, V> node(K key) {
Node<K, V> root = table[index(key)];
return root == null ? null : node(root, key);
}
private Node<K, V> node(Node<K, V> node, K k1) {
int h1 = k1 == null ? 0 : k1.hashCode();
// 存储查找结果
Node<K, V> result = null;
int cmp = 0;
while (node != null) {
K k2 = node.key;
int h2 = node.hash;
// 先比较哈希值
if (h1 > h2) {
node = node.right;
} else if (h1 < h2) {
node = node.left;
} else if (Objects.equals(k1, k2)) {
return node;
} else if (k1 != null && k2 != null
&& k1.getClass() == k2.getClass()
&& k1 instanceof Comparable
&& (cmp = ((Comparable) k1).compareTo(k2)) != 0) {
node = cmp > 0 ? node.right : node.left;
} else if (node.right != null && (result = node(node.right, k1)) != null) {
return result;
} else { // 只能往左边找
node = node.left;
}
// } else if (node.left != null && (result = node(node.left, k1)) != null) {
// return result;
// } else {
// return null;
// }
}
return null;
}
/**
* 根据key生成对应的索引(在桶数组中的位置)
*/
private int index(K key) {
if (key == null) return 0;
int hash = key.hashCode();
return (hash ^ (hash >>> 16)) & (table.length - 1);
}
private int index(Node<K, V> node) {
return (node.hash ^ (node.hash >>> 16)) & (table.length - 1);
}
/**
* 比较key大小
* @param k1
* @param k2
* @param h1 k1的hashCode
* @param h2 k2的hashCode
* @return
*/
// private int compare(K k1, K k2, int h1, int h2) {
// // 比较哈希值
// int result = h1 - h2;
// if (result != 0) return result;
//
// // 比较equals
// if (Objects.equals(k1, k2)) return 0;
//
// // 哈希值相等,但是不equals
// if (k1 != null && k2 != null
// && k1.getClass() == k2.getClass()
// && k1 instanceof Comparable) {
// // 同一种类型并且具备可比较性
// if (k1 instanceof Comparable) {
// return ((Comparable) k1).compareTo(k2);
// }
// }
//
// // 同一种类型,哈希值相等,但是不equals,但是不具备可比较性
// // k1不为null,k2为null
// // k1为null,k2不为null
// return System.identityHashCode(k1) - System.identityHashCode(k2);
// }
private void afterRemove(Node<K, V> node) {
// 如果删除的节点是红色
// 或者 用以取代删除节点的子节点是红色
if (isRed(node)) {
black(node);
return;
}
Node<K, V> parent = node.parent;
if (parent == null) return;
// 删除的是黑色叶子节点【下溢】
// 判断被删除的node是左还是右
boolean left = parent.left == null || node.isLeftChild();
Node<K, V> sibling = left ? parent.right : parent.left;
if (left) { // 被删除的节点在左边,兄弟节点在右边
if (isRed(sibling)) { // 兄弟节点是红色
black(sibling);
red(parent);
rotateLeft(parent);
// 更换兄弟
sibling = parent.right;
}
// 兄弟节点必然是黑色
if (isBlack(sibling.left) && isBlack(sibling.right)) {
// 兄弟节点没有1个红色子节点,父节点要向下跟兄弟节点合并
boolean parentBlack = isBlack(parent);
black(parent);
red(sibling);
if (parentBlack) {
afterRemove(parent);
}
} else { // 兄弟节点至少有1个红色子节点,向兄弟节点借元素
// 兄弟节点的左边是黑色,兄弟要先旋转
if (isBlack(sibling.right)) {
rotateRight(sibling);
sibling = parent.right;
}
color(sibling, colorOf(parent));
black(sibling.right);
black(parent);
rotateLeft(parent);
}
} else { // 被删除的节点在右边,兄弟节点在左边
if (isRed(sibling)) { // 兄弟节点是红色
black(sibling);
red(parent);
rotateRight(parent);
// 更换兄弟
sibling = parent.left;
}
// 兄弟节点必然是黑色
if (isBlack(sibling.left) && isBlack(sibling.right)) {
// 兄弟节点没有1个红色子节点,父节点要向下跟兄弟节点合并
boolean parentBlack = isBlack(parent);
black(parent);
red(sibling);
if (parentBlack) {
afterRemove(parent);
}
} else { // 兄弟节点至少有1个红色子节点,向兄弟节点借元素
// 兄弟节点的左边是黑色,兄弟要先旋转
if (isBlack(sibling.left)) {
rotateLeft(sibling);
sibling = parent.left;
}
color(sibling, colorOf(parent));
black(sibling.left);
black(parent);
rotateRight(parent);
}
}
}
private void afterPut(Node<K, V> node) {
Node<K, V> parent = node.parent;
// 添加的是根节点 或者 上溢到达了根节点
if (parent == null) {
black(node);
return;
}
// 如果父节点是黑色,直接返回
if (isBlack(parent)) return;
// 叔父节点
Node<K, V> uncle = parent.sibling();
// 祖父节点
Node<K, V> grand = red(parent.parent);
if (isRed(uncle)) { // 叔父节点是红色【B树节点上溢】
black(parent);
black(uncle);
// 把祖父节点当做是新添加的节点
afterPut(grand);
return;
}
// 叔父节点不是红色
if (parent.isLeftChild()) { // L
if (node.isLeftChild()) { // LL
black(parent);
} else { // LR
black(node);
rotateLeft(parent);
}
rotateRight(grand);
} else { // R
if (node.isLeftChild()) { // RL
black(node);
rotateRight(parent);
} else { // RR
black(parent);
}
rotateLeft(grand);
}
}
private void rotateLeft(Node<K, V> grand) {
Node<K, V> parent = grand.right;
Node<K, V> child = parent.left;
grand.right = child;
parent.left = grand;
afterRotate(grand, parent, child);
}
private void rotateRight(Node<K, V> grand) {
Node<K, V> parent = grand.left;
Node<K, V> child = parent.right;
grand.left = child;
parent.right = grand;
afterRotate(grand, parent, child);
}
private void afterRotate(Node<K, V> grand, Node<K, V> parent, Node<K, V> child) {
// 让parent称为子树的根节点
parent.parent = grand.parent;
if (grand.isLeftChild()) {
grand.parent.left = parent;
} else if (grand.isRightChild()) {
grand.parent.right = parent;
} else { // grand是root节点
table[index(grand)] = parent;
}
// 更新child的parent
if (child != null) {
child.parent = grand;
}
// 更新grand的parent
grand.parent = parent;
}
private Node<K, V> color(Node<K, V> node, boolean color) {
if (node == null) return node;
node.color = color;
return node;
}
private Node<K, V> red(Node<K, V> node) {
return color(node, RED);
}
private Node<K, V> black(Node<K, V> node) {
return color(node, BLACK);
}
private boolean colorOf(Node<K, V> node) {
return node == null ? BLACK : node.color;
}
private boolean isBlack(Node<K, V> node) {
return colorOf(node) == BLACK;
}
private boolean isRed(Node<K, V> node) {
return colorOf(node) == RED;
}
private static class Node<K, V> {
int hash;
K key;
V value;
boolean color = RED;
Node<K, V> left;
Node<K, V> right;
Node<K, V> parent;
public Node(K key, V value, Node<K, V> parent) {
this.key = key;
this.hash = key == null ? 0 : key.hashCode();
this.value = value;
this.parent = parent;
}
public boolean hasTwoChildren() {
return left != null && right != null;
}
public boolean isLeftChild() {
return parent != null && this == parent.left;
}
public boolean isRightChild() {
return parent != null && this == parent.right;
}
public Node<K, V> sibling() {
if (isLeftChild()) {
return parent.right;
}
if (isRightChild()) {
return parent.left;
}
return null;
}
@Override
public String toString() {
return "Node_" + key + "_" + value;
}
}
}

查看文件

@@ -0,0 +1,18 @@
package com.mj.map;
public interface Map<K, V> {
int size();
boolean isEmpty();
void clear();
V put(K key, V value);
V get(K key);
V remove(K key);
boolean containsKey(K key);
boolean containsValue(V value);
void traversal(Visitor<K, V> visitor);
public static abstract class Visitor<K, V> {
boolean stop;
public abstract boolean visit(K key, V value);
}
}

查看文件

@@ -0,0 +1,486 @@
package com.mj.map;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.Queue;
@SuppressWarnings({"unchecked", "unused"})
public class TreeMap<K, V> implements Map<K, V> {
private static final boolean RED = false;
private static final boolean BLACK = true;
private int size;
private Node<K, V> root;
private Comparator<K> comparator;
public TreeMap() {
this(null);
}
public TreeMap(Comparator<K> comparator) {
this.comparator = comparator;
}
public int size() {
return size;
}
public boolean isEmpty() {
return size == 0;
}
public void clear() {
root = null;
size = 0;
}
@Override
public V put(K key, V value) {
keyNotNullCheck(key);
// 添加第一个节点
if (root == null) {
root = new Node<>(key, value, null);
size++;
// 新添加节点之后的处理
afterPut(root);
return null;
}
// 添加的不是第一个节点
// 找到父节点
Node<K, V> parent = root;
Node<K, V> node = root;
int cmp = 0;
do {
cmp = compare(key, node.key);
parent = node;
if (cmp > 0) {
node = node.right;
} else if (cmp < 0) {
node = node.left;
} else { // 相等
node.key = key;
V oldValue = node.value;
node.value = value;
return oldValue;
}
} while (node != null);
// 看看插入到父节点的哪个位置
Node<K, V> newNode = new Node<>(key, value, parent);
if (cmp > 0) {
parent.right = newNode;
} else {
parent.left = newNode;
}
size++;
// 新添加节点之后的处理
afterPut(newNode);
return null;
}
@Override
public V get(K key) {
Node<K, V> node = node(key);
return node != null ? node.value : null;
}
@Override
public V remove(K key) {
return remove(node(key));
}
@Override
public boolean containsKey(K key) {
return node(key) != null;
}
@Override
public boolean containsValue(V value) {
if (root == null) return false;
Queue<Node<K, V>> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
Node<K, V> node = queue.poll();
if (valEquals(value, node.value)) return true;
if (node.left != null) {
queue.offer(node.left);
}
if (node.right != null) {
queue.offer(node.right);
}
}
return false;
}
@Override
public void traversal(Visitor<K, V> visitor) {
if (visitor == null) return;
traversal(root, visitor);
}
private void traversal(Node<K, V> node, Visitor<K, V> visitor) {
if (node == null || visitor.stop) return;
traversal(node.left, visitor);
if (visitor.stop) return;
visitor.visit(node.key, node.value);
traversal(node.right, visitor);
}
private boolean valEquals(V v1, V v2) {
return v1 == null ? v2 == null : v1.equals(v2);
}
private V remove(Node<K, V> node) {
if (node == null) return null;
size--;
V oldValue = node.value;
if (node.hasTwoChildren()) { // 度为2的节点
// 找到后继节点
Node<K, V> s = successor(node);
// 用后继节点的值覆盖度为2的节点的值
node.key = s.key;
node.value = s.value;
// 删除后继节点
node = s;
}
// 删除node节点(node的度必然是1或者0)
Node<K, V> replacement = node.left != null ? node.left : node.right;
if (replacement != null) { // node是度为1的节点
// 更改parent
replacement.parent = node.parent;
// 更改parent的left、right的指向
if (node.parent == null) { // node是度为1的节点并且是根节点
root = replacement;
} else if (node == node.parent.left) {
node.parent.left = replacement;
} else { // node == node.parent.right
node.parent.right = replacement;
}
// 删除节点之后的处理
afterRemove(replacement);
} else if (node.parent == null) { // node是叶子节点并且是根节点
root = null;
} else { // node是叶子节点,但不是根节点
if (node == node.parent.left) {
node.parent.left = null;
} else { // node == node.parent.right
node.parent.right = null;
}
// 删除节点之后的处理
afterRemove(node);
}
return oldValue;
}
private void afterRemove(Node<K, V> node) {
// 如果删除的节点是红色
// 或者 用以取代删除节点的子节点是红色
if (isRed(node)) {
black(node);
return;
}
Node<K, V> parent = node.parent;
if (parent == null) return;
// 删除的是黑色叶子节点【下溢】
// 判断被删除的node是左还是右
boolean left = parent.left == null || node.isLeftChild();
Node<K, V> sibling = left ? parent.right : parent.left;
if (left) { // 被删除的节点在左边,兄弟节点在右边
if (isRed(sibling)) { // 兄弟节点是红色
black(sibling);
red(parent);
rotateLeft(parent);
// 更换兄弟
sibling = parent.right;
}
// 兄弟节点必然是黑色
if (isBlack(sibling.left) && isBlack(sibling.right)) {
// 兄弟节点没有1个红色子节点,父节点要向下跟兄弟节点合并
boolean parentBlack = isBlack(parent);
black(parent);
red(sibling);
if (parentBlack) {
afterRemove(parent);
}
} else { // 兄弟节点至少有1个红色子节点,向兄弟节点借元素
// 兄弟节点的左边是黑色,兄弟要先旋转
if (isBlack(sibling.right)) {
rotateRight(sibling);
sibling = parent.right;
}
color(sibling, colorOf(parent));
black(sibling.right);
black(parent);
rotateLeft(parent);
}
} else { // 被删除的节点在右边,兄弟节点在左边
if (isRed(sibling)) { // 兄弟节点是红色
black(sibling);
red(parent);
rotateRight(parent);
// 更换兄弟
sibling = parent.left;
}
// 兄弟节点必然是黑色
if (isBlack(sibling.left) && isBlack(sibling.right)) {
// 兄弟节点没有1个红色子节点,父节点要向下跟兄弟节点合并
boolean parentBlack = isBlack(parent);
black(parent);
red(sibling);
if (parentBlack) {
afterRemove(parent);
}
} else { // 兄弟节点至少有1个红色子节点,向兄弟节点借元素
// 兄弟节点的左边是黑色,兄弟要先旋转
if (isBlack(sibling.left)) {
rotateLeft(sibling);
sibling = parent.left;
}
color(sibling, colorOf(parent));
black(sibling.left);
black(parent);
rotateRight(parent);
}
}
}
private Node<K, V> predecessor(Node<K, V> node) {
if (node == null) return null;
// 前驱节点在左子树当中(left.right.right.right....)
Node<K, V> p = node.left;
if (p != null) {
while (p.right != null) {
p = p.right;
}
return p;
}
// 从父节点、祖父节点中寻找前驱节点
while (node.parent != null && node == node.parent.left) {
node = node.parent;
}
// node.parent == null
// node == node.parent.right
return node.parent;
}
private Node<K, V> successor(Node<K, V> node) {
if (node == null) return null;
// 前驱节点在左子树当中(right.left.left.left....)
Node<K, V> p = node.right;
if (p != null) {
while (p.left != null) {
p = p.left;
}
return p;
}
// 从父节点、祖父节点中寻找前驱节点
while (node.parent != null && node == node.parent.right) {
node = node.parent;
}
return node.parent;
}
private Node<K, V> node(K key) {
Node<K, V> node = root;
while (node != null) {
int cmp = compare(key, node.key);
if (cmp == 0) return node;
if (cmp > 0) {
node = node.right;
} else { // cmp < 0
node = node.left;
}
}
return null;
}
private void afterPut(Node<K, V> node) {
Node<K, V> parent = node.parent;
// 添加的是根节点 或者 上溢到达了根节点
if (parent == null) {
black(node);
return;
}
// 如果父节点是黑色,直接返回
if (isBlack(parent)) return;
// 叔父节点
Node<K, V> uncle = parent.sibling();
// 祖父节点
Node<K, V> grand = red(parent.parent);
if (isRed(uncle)) { // 叔父节点是红色【B树节点上溢】
black(parent);
black(uncle);
// 把祖父节点当做是新添加的节点
afterPut(grand);
return;
}
// 叔父节点不是红色
if (parent.isLeftChild()) { // L
if (node.isLeftChild()) { // LL
black(parent);
} else { // LR
black(node);
rotateLeft(parent);
}
rotateRight(grand);
} else { // R
if (node.isLeftChild()) { // RL
black(node);
rotateRight(parent);
} else { // RR
black(parent);
}
rotateLeft(grand);
}
}
private void rotateLeft(Node<K, V> grand) {
Node<K, V> parent = grand.right;
Node<K, V> child = parent.left;
grand.right = child;
parent.left = grand;
afterRotate(grand, parent, child);
}
private void rotateRight(Node<K, V> grand) {
Node<K, V> parent = grand.left;
Node<K, V> child = parent.right;
grand.left = child;
parent.right = grand;
afterRotate(grand, parent, child);
}
private void afterRotate(Node<K, V> grand, Node<K, V> parent, Node<K, V> child) {
// 让parent称为子树的根节点
parent.parent = grand.parent;
if (grand.isLeftChild()) {
grand.parent.left = parent;
} else if (grand.isRightChild()) {
grand.parent.right = parent;
} else { // grand是root节点
root = parent;
}
// 更新child的parent
if (child != null) {
child.parent = grand;
}
// 更新grand的parent
grand.parent = parent;
}
private Node<K, V> color(Node<K, V> node, boolean color) {
if (node == null) return node;
node.color = color;
return node;
}
private Node<K, V> red(Node<K, V> node) {
return color(node, RED);
}
private Node<K, V> black(Node<K, V> node) {
return color(node, BLACK);
}
private boolean colorOf(Node<K, V> node) {
return node == null ? BLACK : node.color;
}
private boolean isBlack(Node<K, V> node) {
return colorOf(node) == BLACK;
}
private boolean isRed(Node<K, V> node) {
return colorOf(node) == RED;
}
private int compare(K e1, K e2) {
if (comparator != null) {
return comparator.compare(e1, e2);
}
return ((Comparable<K>)e1).compareTo(e2);
}
private void keyNotNullCheck(K key) {
if (key == null) {
throw new IllegalArgumentException("key must not be null");
}
}
private static class Node<K, V> {
K key;
V value;
boolean color = RED;
Node<K, V> left;
Node<K, V> right;
Node<K, V> parent;
public Node(K key, V value, Node<K, V> parent) {
this.key = key;
this.value = value;
this.parent = parent;
}
public boolean isLeaf() {
return left == null && right == null;
}
public boolean hasTwoChildren() {
return left != null && right != null;
}
public boolean isLeftChild() {
return parent != null && this == parent.left;
}
public boolean isRightChild() {
return parent != null && this == parent.right;
}
public Node<K, V> sibling() {
if (isLeftChild()) {
return parent.right;
}
if (isRightChild()) {
return parent.left;
}
return null;
}
}
}

查看文件

@@ -0,0 +1,26 @@
package com.mj.model;
public class Key {
protected int value;
public Key(int value) {
this.value = value;
}
@Override
public int hashCode() {
return value / 10;
}
@Override
public boolean equals(Object obj) {
if (obj == this) return true;
if (obj == null || obj.getClass() != getClass()) return false;
return ((Key) obj).value == value;
}
@Override
public String toString() {
return "v(" + value + ")";
}
}

查看文件

@@ -0,0 +1,43 @@
package com.mj.model;
public class Person implements Comparable<Person> {
private int age; // 10 20
private float height; // 1.55 1.67
private String name; // "jack" "rose"
public Person(int age, float height, String name) {
this.age = age;
this.height = height;
this.name = name;
}
@Override
/**
* 用来比较2个对象是否相等
*/
public boolean equals(Object obj) {
// 内存地址
if (this == obj) return true;
if (obj == null || obj.getClass() != getClass()) return false;
// if (obj == null || !(obj instanceof Person)) return false;
// 比较成员变量
Person person = (Person) obj;
return person.age == age
&& person.height == height
&& (person.name == null ? name == null : person.name.equals(name));
}
@Override
public int hashCode() {
int hashCode = Integer.hashCode(age);
hashCode = hashCode * 31 + Float.hashCode(height);
hashCode = hashCode * 31 + (name != null ? name.hashCode() : 0);
return hashCode;
}
@Override
public int compareTo(Person o) {
return age - o.age;
}
}

查看文件

@@ -0,0 +1,10 @@
package com.mj.model;
public class Student extends Person {
public Student(int age, float height, String name) {
super(age, height, name);
// TODO Auto-generated constructor stub
}
}

查看文件

@@ -0,0 +1,17 @@
package com.mj.model;
public class SubKey1 extends Key {
public SubKey1(int value) {
super(value);
}
@Override
public boolean equals(Object obj) {
if (obj == this) return true;
if (obj == null ||
(obj.getClass() != SubKey1.class
&& obj.getClass() != SubKey2.class)) return false;
return ((Key) obj).value == value;
}
}

查看文件

@@ -0,0 +1,17 @@
package com.mj.model;
public class SubKey2 extends Key {
public SubKey2(int value) {
super(value);
}
@Override
public boolean equals(Object obj) {
if (obj == this) return true;
if (obj == null ||
(obj.getClass() != SubKey1.class
&& obj.getClass() != SubKey2.class)) return false;
return ((Key) obj).value == value;
}
}

查看文件

@@ -0,0 +1,20 @@
package com.mj.printer;
public interface BinaryTreeInfo {
/**
* who is the root node
*/
Object root();
/**
* how to get the left child of the node
*/
Object left(Object node);
/**
* how to get the right child of the node
*/
Object right(Object node);
/**
* how to print the node
*/
Object string(Object node);
}

查看文件

@@ -0,0 +1,48 @@
package com.mj.printer;
/**
*
* @author MJ Lee
*
*/
public final class BinaryTrees {
private BinaryTrees() {
}
public static void print(BinaryTreeInfo tree) {
print(tree, null);
}
public static void println(BinaryTreeInfo tree) {
println(tree, null);
}
public static void print(BinaryTreeInfo tree, PrintStyle style) {
if (tree == null || tree.root() == null) return;
printer(tree, style).print();
}
public static void println(BinaryTreeInfo tree, PrintStyle style) {
if (tree == null || tree.root() == null) return;
printer(tree, style).println();
}
public static String printString(BinaryTreeInfo tree) {
return printString(tree, null);
}
public static String printString(BinaryTreeInfo tree, PrintStyle style) {
if (tree == null || tree.root() == null) return null;
return printer(tree, style).printString();
}
private static Printer printer(BinaryTreeInfo tree, PrintStyle style) {
if (style == PrintStyle.INORDER) return new InorderPrinter(tree);
return new LevelOrderPrinter(tree);
}
public enum PrintStyle {
LEVEL_ORDER, INORDER
}
}

查看文件

@@ -0,0 +1,89 @@
package com.mj.printer;
/**
┌──800
┌──760
│ └──600
┌──540
│ └──476
│ └──445
┌──410
│ └──394
381
│ ┌──190
│ │ └──146
│ ┌──40
│ │ └──35
└──12
└──9
* @author MJ Lee
*
*/
public class InorderPrinter extends Printer {
private static String rightAppend;
private static String leftAppend;
private static String blankAppend;
private static String lineAppend;
static {
int length = 2;
rightAppend = "" + Strings.repeat("", length);
leftAppend = "" + Strings.repeat("", length);
blankAppend = Strings.blank(length + 1);
lineAppend = "" + Strings.blank(length);
}
public InorderPrinter(BinaryTreeInfo tree) {
super(tree);
}
@Override
public String printString() {
StringBuilder string = new StringBuilder(
printString(tree.root(), "", "", ""));
string.deleteCharAt(string.length() - 1);
return string.toString();
}
/**
* 生成node节点的字符串
* @param nodePrefix node那一行的前缀字符串
* @param leftPrefix node整棵左子树的前缀字符串
* @param rightPrefix node整棵右子树的前缀字符串
* @return
*/
private String printString(
Object node,
String nodePrefix,
String leftPrefix,
String rightPrefix) {
Object left = tree.left(node);
Object right = tree.right(node);
String string = tree.string(node).toString();
int length = string.length();
if (length % 2 == 0) {
length--;
}
length >>= 1;
String nodeString = "";
if (right != null) {
rightPrefix += Strings.blank(length);
nodeString += printString(right,
rightPrefix + rightAppend,
rightPrefix + lineAppend,
rightPrefix + blankAppend);
}
nodeString += nodePrefix + string + "\n";
if (left != null) {
leftPrefix += Strings.blank(length);
nodeString += printString(left,
leftPrefix + leftAppend,
leftPrefix + blankAppend,
leftPrefix + lineAppend);
}
return nodeString;
}
}

查看文件

@@ -0,0 +1,528 @@
package com.mj.printer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
/**
┌───381────┐
│ │
┌─12─┐ ┌─410─┐
│ │ │ │
9 ┌─40─┐ 394 ┌─540─┐
│ │ │ │
35 ┌─190 ┌─476 ┌─760─┐
│ │ │ │
146 445 600 800
* @author MJ Lee
*
*/
public class LevelOrderPrinter extends Printer {
/**
* 节点之间允许的最小间距(最小只能填1)
*/
private static final int MIN_SPACE = 1;
private Node root;
private int minX;
private int maxWidth;
public LevelOrderPrinter(BinaryTreeInfo tree) {
super(tree);
root = new Node(tree.root(), tree);
maxWidth = root.width;
}
@Override
public String printString() {
// nodes用来存放所有的节点
List<List<Node>> nodes = new ArrayList<>();
fillNodes(nodes);
cleanNodes(nodes);
compressNodes(nodes);
addLineNodes(nodes);
int rowCount = nodes.size();
// 构建字符串
StringBuilder string = new StringBuilder();
for (int i = 0; i < rowCount; i++) {
if (i != 0) {
string.append("\n");
}
List<Node> rowNodes = nodes.get(i);
StringBuilder rowSb = new StringBuilder();
for (Node node : rowNodes) {
int leftSpace = node.x - rowSb.length() - minX;
rowSb.append(Strings.blank(leftSpace));
rowSb.append(node.string);
}
string.append(rowSb);
}
return string.toString();
}
/**
* 添加一个元素节点
*/
private Node addNode(List<Node> nodes, Object btNode) {
Node node = null;
if (btNode != null) {
node = new Node(btNode, tree);
maxWidth = Math.max(maxWidth, node.width);
nodes.add(node);
} else {
nodes.add(null);
}
return node;
}
/**
* 以满二叉树的形式填充节点
*/
private void fillNodes(List<List<Node>> nodes) {
if (nodes == null) return;
// 第一行
List<Node> firstRowNodes = new ArrayList<>();
firstRowNodes.add(root);
nodes.add(firstRowNodes);
// 其他行
while (true) {
List<Node> preRowNodes = nodes.get(nodes.size() - 1);
List<Node> rowNodes = new ArrayList<>();
boolean notNull = false;
for (Node node : preRowNodes) {
if (node == null) {
rowNodes.add(null);
rowNodes.add(null);
} else {
Node left = addNode(rowNodes, tree.left(node.btNode));
if (left != null) {
node.left = left;
left.parent = node;
notNull = true;
}
Node right = addNode(rowNodes, tree.right(node.btNode));
if (right != null) {
node.right = right;
right.parent = node;
notNull = true;
}
}
}
// 全是null,就退出
if (!notNull) break;
nodes.add(rowNodes);
}
}
/**
* 删除全部null、更新节点的坐标
*/
private void cleanNodes(List<List<Node>> nodes) {
if (nodes == null) return;
int rowCount = nodes.size();
if (rowCount < 2) return;
// 最后一行的节点数量
int lastRowNodeCount = nodes.get(rowCount - 1).size();
// 每个节点之间的间距
int nodeSpace = maxWidth + 2;
// 最后一行的长度
int lastRowLength = lastRowNodeCount * maxWidth
+ nodeSpace * (lastRowNodeCount - 1);
// 空集合
Collection<Object> nullSet = Collections.singleton(null);
for (int i = 0; i < rowCount; i++) {
List<Node> rowNodes = nodes.get(i);
int rowNodeCount = rowNodes.size();
// 节点左右两边的间距
int allSpace = lastRowLength - (rowNodeCount - 1) * nodeSpace;
int cornerSpace = allSpace / rowNodeCount - maxWidth;
cornerSpace >>= 1;
int rowLength = 0;
for (int j = 0; j < rowNodeCount; j++) {
if (j != 0) {
// 每个节点之间的间距
rowLength += nodeSpace;
}
rowLength += cornerSpace;
Node node = rowNodes.get(j);
if (node != null) {
// 居中(由于奇偶数的问题,可能有1个符号的误差)
int deltaX = (maxWidth - node.width) >> 1;
node.x = rowLength + deltaX;
node.y = i;
}
rowLength += maxWidth;
rowLength += cornerSpace;
}
// 删除所有的null
rowNodes.removeAll(nullSet);
}
}
/**
* 压缩空格
*/
private void compressNodes(List<List<Node>> nodes) {
if (nodes == null) return;
int rowCount = nodes.size();
if (rowCount < 2) return;
for (int i = rowCount - 2; i >= 0; i--) {
List<Node> rowNodes = nodes.get(i);
for (Node node : rowNodes) {
Node left = node.left;
Node right = node.right;
if (left == null && right == null) continue;
if (left != null && right != null) {
// 让左右节点对称
node.balance(left, right);
// left和right之间可以挪动的最小间距
int leftEmpty = node.leftBoundEmptyLength();
int rightEmpty = node.rightBoundEmptyLength();
int empty = Math.min(leftEmpty, rightEmpty);
empty = Math.min(empty, (right.x - left.rightX()) >> 1);
// left、right的子节点之间可以挪动的最小间距
int space = left.minLevelSpaceToRight(right) - MIN_SPACE;
space = Math.min(space >> 1, empty);
// left、right往中间挪动
if (space > 0) {
left.translateX(space);
right.translateX(-space);
}
// 继续挪动
space = left.minLevelSpaceToRight(right) - MIN_SPACE;
if (space < 1) continue;
// 可以继续挪动的间距
leftEmpty = node.leftBoundEmptyLength();
rightEmpty = node.rightBoundEmptyLength();
if (leftEmpty < 1 && rightEmpty < 1) continue;
if (leftEmpty > rightEmpty) {
left.translateX(Math.min(leftEmpty, space));
} else {
right.translateX(-Math.min(rightEmpty, space));
}
} else if (left != null) {
left.translateX(node.leftBoundEmptyLength());
} else { // right != null
right.translateX(-node.rightBoundEmptyLength());
}
}
}
}
private void addXLineNode(List<Node> curRow, Node parent, int x) {
Node line = new Node("");
line.x = x;
line.y = parent.y;
curRow.add(line);
}
private Node addLineNode(List<Node> curRow, List<Node> nextRow, Node parent, Node child) {
if (child == null) return null;
Node top = null;
int topX = child.topLineX();
if (child == parent.left) {
top = new Node("");
curRow.add(top);
for (int x = topX + 1; x < parent.x; x++) {
addXLineNode(curRow, parent, x);
}
} else {
for (int x = parent.rightX(); x < topX; x++) {
addXLineNode(curRow, parent, x);
}
top = new Node("");
curRow.add(top);
}
// 坐标
top.x = topX;
top.y = parent.y;
child.y = parent.y + 2;
minX = Math.min(minX, child.x);
// 竖线
Node bottom = new Node("");
bottom.x = topX;
bottom.y = parent.y + 1;
nextRow.add(bottom);
return top;
}
private void addLineNodes(List<List<Node>> nodes) {
List<List<Node>> newNodes = new ArrayList<>();
int rowCount = nodes.size();
if (rowCount < 2) return;
minX = root.x;
for (int i = 0; i < rowCount; i++) {
List<Node> rowNodes = nodes.get(i);
if (i == rowCount - 1) {
newNodes.add(rowNodes);
continue;
}
List<Node> newRowNodes = new ArrayList<>();
newNodes.add(newRowNodes);
List<Node> lineNodes = new ArrayList<>();
newNodes.add(lineNodes);
for (Node node : rowNodes) {
addLineNode(newRowNodes, lineNodes, node, node.left);
newRowNodes.add(node);
addLineNode(newRowNodes, lineNodes, node, node.right);
}
}
nodes.clear();
nodes.addAll(newNodes);
}
private static class Node {
/**
* 顶部符号距离父节点的最小距离(最小能填0)
*/
private static final int TOP_LINE_SPACE = 1;
Object btNode;
Node left;
Node right;
Node parent;
/**
* 首字符的位置
*/
int x;
int y;
int treeHeight;
String string;
int width;
private void init(String string) {
string = (string == null) ? "null" : string;
string = string.isEmpty() ? " " : string;
width = string.length();
this.string = string;
}
public Node(String string) {
init(string);
}
public Node(Object btNode, BinaryTreeInfo opetaion) {
init(opetaion.string(btNode).toString());
this.btNode = btNode;
}
/**
* 顶部方向字符的X(极其重要)
*
* @return
*/
private int topLineX() {
// 宽度的一半
int delta = width;
if (delta % 2 == 0) {
delta--;
}
delta >>= 1;
if (parent != null && this == parent.left) {
return rightX() - 1 - delta;
} else {
return x + delta;
}
}
/**
* 右边界的位置(rightX 或者 右子节点topLineX的下一个位置)(极其重要)
*/
private int rightBound() {
if (right == null) return rightX();
return right.topLineX() + 1;
}
/**
* 左边界的位置(x 或者 左子节点topLineX)(极其重要)
*/
private int leftBound() {
if (left == null) return x;
return left.topLineX();
}
/**
* x ~ 左边界之间的长度(包括左边界字符)
*
* @return
*/
private int leftBoundLength() {
return x - leftBound();
}
/**
* rightX ~ 右边界之间的长度(包括右边界字符)
*
* @return
*/
private int rightBoundLength() {
return rightBound() - rightX();
}
/**
* 左边界可以清空的长度
*
* @return
*/
private int leftBoundEmptyLength() {
return leftBoundLength() - 1 - TOP_LINE_SPACE;
}
/**
* 右边界可以清空的长度
*
* @return
*/
private int rightBoundEmptyLength() {
return rightBoundLength() - 1 - TOP_LINE_SPACE;
}
/**
* 让left和right基于this对称
*/
private void balance(Node left, Node right) {
if (left == null || right == null)
return;
// 【left的尾字符】与【this的首字符】之间的间距
int deltaLeft = x - left.rightX();
// 【this的尾字符】与【this的首字符】之间的间距
int deltaRight = right.x - rightX();
int delta = Math.max(deltaLeft, deltaRight);
int newRightX = rightX() + delta;
right.translateX(newRightX - right.x);
int newLeftX = x - delta - left.width;
left.translateX(newLeftX - left.x);
}
private int treeHeight(Node node) {
if (node == null) return 0;
if (node.treeHeight != 0) return node.treeHeight;
node.treeHeight = 1 + Math.max(
treeHeight(node.left), treeHeight(node.right));
return node.treeHeight;
}
/**
* 和右节点之间的最小层级距离
*/
private int minLevelSpaceToRight(Node right) {
int thisHeight = treeHeight(this);
int rightHeight = treeHeight(right);
int minSpace = Integer.MAX_VALUE;
for (int i = 0; i < thisHeight && i < rightHeight; i++) {
int space = right.levelInfo(i).leftX
- this.levelInfo(i).rightX;
minSpace = Math.min(minSpace, space);
}
return minSpace;
}
private LevelInfo levelInfo(int level) {
if (level < 0) return null;
int levelY = y + level;
if (level >= treeHeight(this)) return null;
List<Node> list = new ArrayList<>();
Queue<Node> queue = new LinkedList<>();
queue.offer(this);
// 层序遍历找出第level行的所有节点
while (!queue.isEmpty()) {
Node node = queue.poll();
if (levelY == node.y) {
list.add(node);
} else if (node.y > levelY) break;
if (node.left != null) {
queue.offer(node.left);
}
if (node.right != null) {
queue.offer(node.right);
}
}
Node left = list.get(0);
Node right = list.get(list.size() - 1);
return new LevelInfo(left, right);
}
/**
* 尾字符的下一个位置
*/
public int rightX() {
return x + width;
}
public void translateX(int deltaX) {
if (deltaX == 0) return;
x += deltaX;
// 如果是LineNode
if (btNode == null) return;
if (left != null) {
left.translateX(deltaX);
}
if (right != null) {
right.translateX(deltaX);
}
}
}
private static class LevelInfo {
int leftX;
int rightX;
public LevelInfo(Node left, Node right) {
this.leftX = left.leftBound();
this.rightX = right.rightBound();
}
}
}

查看文件

@@ -0,0 +1,32 @@
package com.mj.printer;
public abstract class Printer {
/**
* 二叉树的基本信息
*/
protected BinaryTreeInfo tree;
public Printer(BinaryTreeInfo tree) {
this.tree = tree;
}
/**
* 生成打印的字符串
*/
public abstract String printString();
/**
* 打印后换行
*/
public void println() {
print();
System.out.println();
}
/**
* 打印
*/
public void print() {
System.out.print(printString());
}
}

查看文件

@@ -0,0 +1,19 @@
package com.mj.printer;
public class Strings {
public static String repeat(String string, int count) {
if (string == null) return null;
StringBuilder builder = new StringBuilder();
while (count-- > 0) {
builder.append(string);
}
return builder.toString();
}
public static String blank(int length) {
if (length < 0) return null;
if (length == 0) return "";
return String.format("%" + length + "s", "");
}
}