class Node<K> {
Node(K data) {
this.data = data;
this.left = null;
this.right = null;
this.parent = null;
}
Node(K data, Node<K> left, Node<K> right, Node<K> parent) {
this.data = data;
this.left = left;
this. right = right;
this.parent = parent;
}
K data;
Node<K> left;
Node<K> right;
Node<K> parent;
}
public void preOrderTraversal(Consumer<E> action) {
preOrderTraversal(root, action);
}
private void preOrderTraversal(Node<E> node, Consumer<E> action) {
if (Objects.isNull(node)) {
return;
}
Deque<Node<E>> tube = new ArrayDeque<>();
tube.push(node);
while (!tube.isEmpty()) {
node = tube.poll();
action.accept(node.data);
// 先让右子节点入栈
if (!Objects.isNull(node.right)) {
tube.push(node.right);
}
// 再让左子节点入栈
if (!Objects.isNull(node.left)) {
tube.push(node.left);
}
}
}
public void inOrderTraversal(Consumer<E> action) {
inOrderTraversal(root, action);
}
private void inOrderTraversal(Node<E> node, Consumer<E> action) {
if (Objects.isNull(node)) {
return;
}
Deque<Node<E>> tube = new ArrayDeque<>();
Node<E> cur = node;
while (!tube.isEmpty() || !Objects.isNull(cur)) {
if (!Objects.isNull(cur)) {
tube.push(cur);
cur = cur.left;
} else {
cur = tube.poll();
action.accept(cur.data);
cur = cur.right;
}
}
}
public void postOrderTraversal(Consumer<E> action) {
postOrderTraversal(root, action);
}
private void postOrderTraversal(Node<E> node, Consumer<E> action) {
if (Objects.isNull(node)) {
return;
}
Deque<Node<E>> tube = new ArrayDeque<>();
Node<E> cur = node;
Node<E> lastVisited = null;
while (!tube.isEmpty() || !Objects.isNull(cur)) {
if (!Objects.isNull(cur)) {
tube.push(cur);
cur = cur.left;
} else {
cur = tube.peek();
if (Objects.isNull(cur.right) || lastVisited == cur.right) {
action.accept(cur.data);
lastVisited = cur;
tube.poll();
// 此处十分关键,否则会导致严重错误!
cur = null;
} else {
cur = cur.right;
}
}
}
}
public void levelOrderTraversal(Consumer<E> action) {
levelOrderTraversal(root, action);
}
private void levelOrderTraversal(Node<E> node, Consumer<E> action) {
if (Objects.isNull(node)) {
return;
}
/*
层次遍历使用队列作为辅助结构
1. 访问父节点
2. 依次将左子节点和右子节点压入队列(如果有的话)
3. 从队列中提取元素并访问
4. GOTO 1
循环终止条件:队列为空
*/
Deque<Node<E>> tube = new ArrayDeque<>();
tube.offer(node);
while (!tube.isEmpty()) {
Node<E> cur = tube.peek();
if (!Objects.isNull(cur.left)) {
tube.offer(cur.left);
}
if (!Objects.isNull(cur.right)) {
tube.offer(cur.right);
}
action.accept(cur.data);
tube.poll();
}
}
public int getHeight() {
return getHeight(root);
}
private int getHeight(Node<E> startNode) {
if (Objects.isNull(startNode)) {
return 0;
}
/*
height = max(LeftHeight, RightHeight) + 1
使用层次遍历的思路,层数即树高
实现要点:确保队列的长度刚好等于该层的节点数量
*/
Deque<Node<E>> tube = new ArrayDeque<>();
tube.offer(startNode);
int height = 0;
while (!tube.isEmpty()) {
++height;
int currentLevelSize = tube.size();
for (int count = 1; count <= currentLevelSize; ++count) {
Node<E> cur = tube.poll();
if (!Objects.isNull(cur.left)) {
tube.offer(cur.left);
}
if (!Objects.isNull(cur.right)) {
tube.offer(cur.right);
}
}
}
return height;
}