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

此提交包含在:
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>06-二叉搜索树</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,483 @@
package com.mj;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.Queue;
import com.mj.printer.BinaryTreeInfo;
@SuppressWarnings("unchecked")
public class BinarySearchTree<E> implements BinaryTreeInfo {
private int size;
private Node<E> root;
private Comparator<E> comparator;
public BinarySearchTree() {
this(null);
}
public BinarySearchTree(Comparator<E> comparator) {
this.comparator = comparator;
}
public int size() {
return size;
}
public boolean isEmpty() {
return size == 0;
}
public void clear() {
root = null;
size = 0;
}
public void add(E element) {
elementNotNullCheck(element);
// 添加第一个节点
if (root == null) {
root = new Node<>(element, null);
size++;
return;
}
// 添加的不是第一个节点
// 找到父节点
Node<E> parent = root;
Node<E> node = root;
int cmp = 0;
do {
cmp = compare(element, node.element);
parent = node;
if (cmp > 0) {
node = node.right;
} else if (cmp < 0) {
node = node.left;
} else { // 相等
node.element = element;
return;
}
} while (node != null);
// 看看插入到父节点的哪个位置
Node<E> newNode = new Node<>(element, parent);
if (cmp > 0) {
parent.right = newNode;
} else {
parent.left = newNode;
}
size++;
}
public void remove(E element) {
remove(node(element));
}
public boolean contains(E element) {
return node(element) != null;
}
private void remove(Node<E> node) {
if (node == null) return;
size--;
if (node.hasTwoChildren()) { // 度为2的节点
// 找到后继节点
Node<E> s = successor(node);
// 用后继节点的值覆盖度为2的节点的值
node.element = s.element;
// 删除后继节点
node = s;
}
// 删除node节点(node的度必然是1或者0)
Node<E> 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;
}
} 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;
}
}
}
private Node<E> node(E element) {
Node<E> node = root;
while (node != null) {
int cmp = compare(element, node.element);
if (cmp == 0) return node;
if (cmp > 0) {
node = node.right;
} else { // cmp < 0
node = node.left;
}
}
return null;
}
// /**
// * 前序遍历
// */
// public void preorderTraversal() {
// preorderTraversal(root);
// }
//
// private void preorderTraversal(Node<E> node) {
// if (node == null) return;
//
// System.out.println(node.element);
// preorderTraversal(node.left);
// preorderTraversal(node.right);
// }
//
// /**
// * 中序遍历
// */
// public void inorderTraversal() {
// inorderTraversal(root);
// }
//
// private void inorderTraversal(Node<E> node) {
// if (node == null) return;
//
// inorderTraversal(node.left);
// System.out.println(node.element);
// inorderTraversal(node.right);
// }
//
// /**
// * 后序遍历
// */
// public void postorderTraversal() {
// postorderTraversal(root);
// }
//
// private void postorderTraversal(Node<E> node) {
// if (node == null) return;
//
// postorderTraversal(node.left);
// postorderTraversal(node.right);
// System.out.println(node.element);
// }
//
// /**
// * 层序遍历
// */
// public void levelOrderTraversal() {
// if (root == null) return;
//
// Queue<Node<E>> queue = new LinkedList<>();
// queue.offer(root);
//
// while (!queue.isEmpty()) {
// Node<E> node = queue.poll();
// System.out.println(node.element);
//
// if (node.left != null) {
// queue.offer(node.left);
// }
//
// if (node.right != null) {
// queue.offer(node.right);
// }
// }
// }
public void preorder(Visitor<E> visitor) {
if (visitor == null) return;
preorder(root, visitor);
}
private void preorder(Node<E> node, Visitor<E> visitor) {
if (node == null || visitor.stop) return;
visitor.stop = visitor.visit(node.element);
preorder(node.left, visitor);
preorder(node.right, visitor);
}
public void inorder(Visitor<E> visitor) {
if (visitor == null) return;
inorder(root, visitor);
}
private void inorder(Node<E> node, Visitor<E> visitor) {
if (node == null || visitor.stop) return;
inorder(node.left, visitor);
if (visitor.stop) return;
visitor.stop = visitor.visit(node.element);
inorder(node.right, visitor);
}
public void postorder(Visitor<E> visitor) {
if (visitor == null) return;
postorder(root, visitor);
}
private void postorder(Node<E> node, Visitor<E> visitor) {
if (node == null || visitor.stop) return;
postorder(node.left, visitor);
postorder(node.right, visitor);
if (visitor.stop) return;
visitor.stop = visitor.visit(node.element);
}
public void levelOrder(Visitor<E> visitor) {
if (root == null || visitor == null) return;
Queue<Node<E>> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
Node<E> node = queue.poll();
if (visitor.visit(node.element)) return;
if (node.left != null) {
queue.offer(node.left);
}
if (node.right != null) {
queue.offer(node.right);
}
}
}
public boolean isComplete() {
if (root == null) return false;
Queue<Node<E>> queue = new LinkedList<>();
queue.offer(root);
boolean leaf = false;
while (!queue.isEmpty()) {
Node<E> node = queue.poll();
if (leaf && !node.isLeaf()) return false;
if (node.left != null) {
queue.offer(node.left);
} else if (node.right != null) { // node.left == null && node.right != null
return false;
}
if (node.right != null) {
queue.offer(node.right);
} else { // node.right == null
leaf = true;
}
}
return true;
}
// public boolean isComplete() {
// if (root == null) return false;
//
// Queue<Node<E>> queue = new LinkedList<>();
// queue.offer(root);
//
// boolean leaf = false;
// while (!queue.isEmpty()) {
// Node<E> node = queue.poll();
// if (leaf && !node.isLeaf()) return false;
//
// if (node.left != null && node.right != null) {
// queue.offer(node.left);
// queue.offer(node.right);
// } else if (node.left == null && node.right != null) {
// return false;
// } else { // 后面遍历的节点都必须是叶子节点
// leaf = true;
// if (node.left != null) {
// queue.offer(node.left);
// }
// }
// }
//
// return true;
// }
public int height() {
if (root == null) return 0;
// 树的高度
int height = 0;
// 存储着每一层的元素数量
int levelSize = 1;
Queue<Node<E>> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
Node<E> node = queue.poll();
levelSize--;
if (node.left != null) {
queue.offer(node.left);
}
if (node.right != null) {
queue.offer(node.right);
}
if (levelSize == 0) { // 意味着即将要访问下一层
levelSize = queue.size();
height++;
}
}
return height;
}
public int height2() {
return height(root);
}
private int height(Node<E> node) {
if (node == null) return 0;
return 1 + Math.max(height(node.left), height(node.right));
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
toString(root, sb, "");
return sb.toString();
}
private void toString(Node<E> node, StringBuilder sb, String prefix) {
if (node == null) return;
toString(node.left, sb, prefix + "L---");
sb.append(prefix).append(node.element).append("\n");
toString(node.right, sb, prefix + "R---");
}
/**
* @return 返回值等于0,代表e1和e2相等返回值大于0,代表e1大于e2返回值小于于0,代表e1小于e2
*/
private int compare(E e1, E e2) {
if (comparator != null) {
return comparator.compare(e1, e2);
}
return ((Comparable<E>)e1).compareTo(e2);
}
private void elementNotNullCheck(E element) {
if (element == null) {
throw new IllegalArgumentException("element must not be null");
}
}
@SuppressWarnings("unused")
private Node<E> predecessor(Node<E> node) {
if (node == null) return null;
// 前驱节点在左子树当中(left.right.right.right....)
Node<E> 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<E> successor(Node<E> node) {
if (node == null) return null;
// 前驱节点在左子树当中(right.left.left.left....)
Node<E> 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;
}
public static abstract class Visitor<E> {
boolean stop;
/**
* @return 如果返回true,就代表停止遍历
*/
public abstract boolean visit(E element);
}
private static class Node<E> {
E element;
Node<E> left;
Node<E> right;
Node<E> parent;
public Node(E element, Node<E> parent) {
this.element = element;
this.parent = parent;
}
public boolean isLeaf() {
return left == null && right == null;
}
public boolean hasTwoChildren() {
return left != null && right != null;
}
}
@Override
public Object root() {
return root;
}
@Override
public Object left(Object node) {
return ((Node<E>)node).left;
}
@Override
public Object right(Object node) {
return ((Node<E>)node).right;
}
@Override
public Object string(Object node) {
Node<E> myNode = (Node<E>)node;
String parentString = "null";
if (myNode.parent != null) {
parentString = myNode.parent.element.toString();
}
return myNode.element + "_p(" + parentString + ")";
}
}

查看文件

@@ -0,0 +1,5 @@
package com.mj;
public class Car {
}

查看文件

@@ -0,0 +1,258 @@
package com.mj;
import java.util.Comparator;
import com.mj.BinarySearchTree.Visitor;
import com.mj.file.Files;
import com.mj.printer.BinaryTreeInfo;
import com.mj.printer.BinaryTrees;
@SuppressWarnings("unused")
public class Main {
private static class PersonComparator implements Comparator<Person> {
public int compare(Person e1, Person e2) {
return e1.getAge() - e2.getAge();
}
}
private static class PersonComparator2 implements Comparator<Person> {
public int compare(Person e1, Person e2) {
return e2.getAge() - e1.getAge();
}
}
static void test1() {
Integer data[] = new Integer[] {
7, 4, 9, 2, 5, 8, 11, 3, 12, 1
};
BinarySearchTree<Integer> bst = new BinarySearchTree<>();
for (int i = 0; i < data.length; i++) {
bst.add(data[i]);
}
BinaryTrees.println(bst);
}
static void test2() {
Integer data[] = new Integer[] {
7, 4, 9, 2, 5, 8, 11, 3, 12, 1
};
BinarySearchTree<Person> bst1 = new BinarySearchTree<>();
for (int i = 0; i < data.length; i++) {
bst1.add(new Person(data[i]));
}
BinaryTrees.println(bst1);
BinarySearchTree<Person> bst2 = new BinarySearchTree<>(new Comparator<Person>() {
public int compare(Person o1, Person o2) {
return o2.getAge() - o1.getAge();
}
});
for (int i = 0; i < data.length; i++) {
bst2.add(new Person(data[i]));
}
BinaryTrees.println(bst2);
}
static void test3() {
BinarySearchTree<Integer> bst = new BinarySearchTree<>();
for (int i = 0; i < 40; i++) {
bst.add((int)(Math.random() * 100));
}
String str = BinaryTrees.printString(bst);
str += "\n";
Files.writeToFile("F:/1.txt", str, true);
// BinaryTrees.println(bst);
}
static void test4() {
BinaryTrees.println(new BinaryTreeInfo() {
@Override
public Object string(Object node) {
return node.toString() + "_";
}
@Override
public Object root() {
return "A";
}
@Override
public Object right(Object node) {
if (node.equals("A")) return "C";
if (node.equals("C")) return "E";
return null;
}
@Override
public Object left(Object node) {
if (node.equals("A")) return "B";
if (node.equals("C")) return "D";
return null;
}
});
// test3();
/*
* Java的匿名类,类似于iOS中的Block、JS中的闭包(function)
*/
// BinarySearchTree<Person> bst1 = new BinarySearchTree<>(new Comparator<Person>() {
// @Override
// public int compare(Person o1, Person o2) {
// return 0;
// }
// });
// bst1.add(new Person(12));
// bst1.add(new Person(15));
//
// BinarySearchTree<Person> bst2 = new BinarySearchTree<>(new PersonComparator());
// bst2.add(new Person(12));
// bst2.add(new Person(15));
//
// BinarySearchTree<Car> bst4 = new BinarySearchTree<>(new Car);
//
//
// java.util.Comparator<Integer> iComparator;
}
static void test5() {
BinarySearchTree<Person> bst = new BinarySearchTree<>();
bst.add(new Person(10, "jack"));
bst.add(new Person(12, "rose"));
bst.add(new Person(6, "jim"));
bst.add(new Person(10, "michael"));
BinaryTrees.println(bst);
}
static void test6() {
Integer data[] = new Integer[] {
7, 4, 9, 2, 5
};
BinarySearchTree<Integer> bst = new BinarySearchTree<>();
for (int i = 0; i < data.length; i++) {
bst.add(data[i]);
}
// BinarySearchTree<Integer> bst = new BinarySearchTree<>();
// for (int i = 0; i < 10; i++) {
// bst.add((int)(Math.random() * 100));
// }
BinaryTrees.println(bst);
System.out.println(bst.isComplete());
// bst.levelOrderTraversal();
/*
* 7
* 4 9
2 5
*/
// bst.levelOrder(new Visitor<Integer>() {
// public void visit(Integer element) {
// System.out.print("_" + element + "_ ");
// }
// });
// bst.inorder(new Visitor<Integer>() {
// public void visit(Integer element) {
// System.out.print("_" + (element + 3) + "_ ");
// }
// });
// System.out.println(bst.height());
}
static void test7() {
Integer data[] = new Integer[] {
7, 4, 9, 2, 5, 8, 11, 3, 12, 1
};
BinarySearchTree<Integer> bst = new BinarySearchTree<>();
for (int i = 0; i < data.length; i++) {
bst.add(data[i]);
}
BinaryTrees.println(bst);
bst.remove(7);
BinaryTrees.println(bst);
}
static void test8() {
Integer data[] = new Integer[] {
7, 4, 9, 2, 1
};
BinarySearchTree<Integer> bst = new BinarySearchTree<>();
for (int i = 0; i < data.length; i++) {
bst.add(data[i]);
}
BinaryTrees.println(bst);
System.out.println(bst.isComplete());
}
static void test9() {
Integer data[] = new Integer[] {
7, 4, 9, 2, 1
};
BinarySearchTree<Integer> bst = new BinarySearchTree<>();
for (int i = 0; i < data.length; i++) {
bst.add(data[i]);
}
BinaryTrees.println(bst);
bst.preorder(new Visitor<Integer>() {
public boolean visit(Integer element) {
System.out.print(element + " ");
return element == 2 ? true : false;
}
});
System.out.println();
bst.inorder(new Visitor<Integer>() {
public boolean visit(Integer element) {
System.out.print(element + " ");
return element == 4 ? true : false;
}
});
System.out.println();
bst.postorder(new Visitor<Integer>() {
public boolean visit(Integer element) {
System.out.print(element + " ");
return element == 4 ? true : false;
}
});
System.out.println();
bst.levelOrder(new Visitor<Integer>() {
public boolean visit(Integer element) {
System.out.print(element + " ");
return element == 9 ? true : false;
}
});
System.out.println();
}
public static void main(String[] args) {
test9();
}
}

查看文件

@@ -0,0 +1,37 @@
package com.mj;
public class Person implements Comparable<Person> {
private int age;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Person(int age) {
this.age = age;
}
public Person(int age, String name) {
this.age = age;
this.name = name;
}
@Override
public int compareTo(Person e) {
// if (age > e.age) return 1;
// if (age < e.age) return -1;
// return 0;
return age - e.age;
}
@Override
public String toString() {
return age + "_" + name;
}
}

查看文件

@@ -0,0 +1,33 @@
package com.mj.file;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
public class Files {
public static void writeToFile(String filePath, Object data) {
writeToFile(filePath, data, false);
}
public static void writeToFile(String filePath, Object data, boolean append) {
if (filePath == null || data == null) return;
try {
File file = new File(filePath);
if (!file.exists()) {
file.getParentFile().mkdirs();
file.createNewFile();
}
try (FileWriter writer = new FileWriter(file, append);
BufferedWriter out = new BufferedWriter(writer) ) {
out.write(data.toString());
out.flush();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

查看文件

@@ -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", "");
}
}