Adds tree iterators based on CPS defunctionalization

Abhinav Sarkar 2019-07-17 10:35:59 +05:30
parent 70e2911852
commit 84161ab2ed
1 changed files with 386 additions and 0 deletions

View File

@ -0,0 +1,386 @@
package net.abhinavsarkar.algorist;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.function.Consumer;
class TreeIerators {
public static void main(String[] args) {
Tree<String> tree =
new Tree<>(new Tree<>(new Tree<>(null, "x", null), "a", null),
"b",
new Tree<>(new Tree<>(null, "o", null), "c", new Tree<>(null, "r", null)));
// InOrderIterator
InOrderIterator.iterateRecursive(tree, System.out::print);
System.out.println("\tInOrderIterator.iterateRecursive");
InOrderIterator.iterateCPS(tree, System.out::print, () -> {});
System.out.println("\tInOrderIterator.iterateCPS");
InOrderIterator.iterateDefCPS(tree, System.out::print, null);
System.out.println("\tInOrderIterator.iterateDefCPS");
InOrderIterator.iterate(tree, System.out::print, null);
System.out.println("\tInOrderIterator.iterate");
InOrderIterator<String> inOrderIterator = new InOrderIterator<>(tree);
while (inOrderIterator.hasNext()) {
System.out.print(inOrderIterator.next());
}
System.out.println("\tInOrderIterator");
System.out.println();
// PreOrderIterator
PreOrderIterator.iterateRecursive(tree, System.out::print);
System.out.println("\tPreOrderIterator.iterateRecursive");
PreOrderIterator.iterateCPS(tree, System.out::print, () -> {});
System.out.println("\tPreOrderIterator.iterateCPS");
PreOrderIterator.iterateDefCPS(tree, System.out::print, null);
System.out.println("\tPreOrderIterator.iterateDefCPS");
PreOrderIterator.iterate(tree, System.out::print, null);
System.out.println("\tPreOrderIterator.iterate");
PreOrderIterator<String> preOrderIterator = new PreOrderIterator<>(tree);
while (preOrderIterator.hasNext()) {
System.out.print(preOrderIterator.next());
}
System.out.println("\tPreOrderIterator");
System.out.println();
PostOrderIterator.iterateRecursive(tree, System.out::print);
System.out.println("\tPostOrderIterator.iterateRecursive");
// PostOrderIterator
PostOrderIterator.iterateCPS(tree, System.out::print, () -> {});
System.out.println("\tPostOrderIterator.iterateCPS");
PostOrderIterator.iterateDefCPS(tree, System.out::print, null);
System.out.println("\tPostOrderIterator.iterateDefCPS");
PostOrderIterator.iterate(tree, System.out::print, null);
System.out.println("\tPostOrderIterator.iterate");
PostOrderIterator<String> postOrderIterator = new PostOrderIterator<>(tree);
while (postOrderIterator.hasNext()) {
System.out.print(postOrderIterator.next());
}
System.out.println("\tPostOrderIterator");
}
}
class Tree<T> {
Tree<T> left;
T content;
Tree<T> right;
Tree(Tree<T> left, T content, Tree<T> right) {
this.left = left;
this.content = content;
this.right = right;
}
@Override
public String toString() {
return content.toString();
}
}
class InOrderIterator<T> implements Iterator<T> {
private static class Cont<T> {
Tree<T> tree;
Cont<T> next;
Cont(Tree<T> tree, Cont<T> next) {
this.tree = tree;
this.next = next;
}
}
static <T> void iterateRecursive(Tree<T> tree, Consumer<T> action) {
if (tree != null) {
iterateRecursive(tree.left, action);
action.accept(tree.content);
iterateRecursive(tree.right, action);
}
}
static <T> void iterateCPS(Tree<T> tree, Consumer<T> action, Runnable cont) {
if (tree != null) {
iterateCPS(tree.left, action, () -> {
action.accept(tree.content);
iterateCPS(tree.right, action, cont);
});
} else {
cont.run();
}
}
static <T> void iterateDefCPS(Tree<T> tree, Consumer<T> action, Cont<T> cont) {
if (tree != null) {
iterateDefCPS(tree.left, action, new Cont<>(tree, cont));
} else {
if (cont != null) {
action.accept(cont.tree.content);
iterateDefCPS(cont.tree.right, action, cont.next);
} else {
return;
}
}
}
static <T> void iterate(Tree<T> tree, Consumer<T> action, Cont<T> cont) {
while (true) {
if (tree != null) {
cont = new Cont<>(tree, cont);
tree = tree.left;
} else {
if (cont != null) {
action.accept(cont.tree.content);
tree = cont.tree.right;
cont = cont.next;
} else {
return;
}
}
}
}
private Tree<T> tree;
private Cont<T> cont;
InOrderIterator(Tree<T> tree) {
this.tree = tree;
}
@Override
public boolean hasNext() {
return tree != null || cont != null;
}
@Override
public T next() {
while (hasNext()) {
if (tree != null) {
cont = new Cont<>(tree, cont);
tree = tree.left;
} else {
if (cont != null) {
T content = cont.tree.content;
tree = cont.tree.right;
cont = cont.next;
return content;
}
}
}
throw new NoSuchElementException();
}
}
class PreOrderIterator<T> implements Iterator<T> {
private static class Cont<T> {
Tree<T> tree;
Cont<T> next;
Cont(Tree<T> tree, Cont<T> next) {
this.tree = tree;
this.next = next;
}
}
static <T> void iterateRecursive(Tree<T> tree, Consumer<T> action) {
if (tree != null) {
action.accept(tree.content);
iterateRecursive(tree.left, action);
iterateRecursive(tree.right, action);
}
}
static <T> void iterateCPS(Tree<T> tree, Consumer<T> action, Runnable cont) {
if (tree != null) {
action.accept(tree.content);
iterateCPS(tree.left, action, () -> iterateCPS(tree.right, action, cont));
} else {
cont.run();
}
}
static <T> void iterateDefCPS(Tree<T> tree, Consumer<T> action, Cont<T> cont) {
if (tree != null) {
action.accept(tree.content);
iterateDefCPS(tree.left, action, tree.right != null ? new Cont<>(tree.right, cont) : cont);
} else {
if (cont != null) {
iterateDefCPS(cont.tree, action, cont.next);
} else {
return;
}
}
}
static <T> void iterate(Tree<T> tree, Consumer<T> action, Cont<T> cont) {
while (true) {
if (tree != null) {
action.accept(tree.content);
if (tree.right != null) {
cont = new Cont<>(tree.right, cont);
}
tree = tree.left;
} else {
if (cont != null) {
tree = cont.tree;
cont = cont.next;
} else {
return;
}
}
}
}
private Tree<T> tree;
private Cont<T> cont;
PreOrderIterator(Tree<T> tree) {
this.tree = tree;
}
@Override
public boolean hasNext() {
return tree != null || cont != null;
}
@Override
public T next() {
while (hasNext()) {
if (tree != null) {
T content = tree.content;
if (tree.right != null) {
cont = new Cont<>(tree.right, cont);
}
tree = tree.left;
return content;
} else {
if (cont != null) {
tree = cont.tree;
cont = cont.next;
}
}
}
throw new NoSuchElementException();
}
}
class PostOrderIterator<T> implements Iterator<T> {
static class Cont<T> {
Tree<T> tree;
boolean isRight;
Cont<T> next;
Cont(Tree<T> tree, boolean isRight, Cont<T> next) {
this.tree = tree;
this.next = next;
this.isRight = isRight;
}
}
static <T> void iterateRecursive(Tree<T> tree, Consumer<T> action) {
if (tree != null) {
iterateRecursive(tree.left, action);
iterateRecursive(tree.right, action);
action.accept(tree.content);
}
}
static <T> void iterateCPS(Tree<T> tree, Consumer<T> action, Runnable cont) {
if (tree != null) {
iterateCPS(tree.left, action, () -> iterateCPS(tree.right, action, () -> {
action.accept(tree.content);
cont.run();
}));
} else {
cont.run();
}
}
static <T> void iterateDefCPS(Tree<T> tree, Consumer<T> action, Cont<T> cont) {
if (cont == null && tree == null) {
return;
}
if (tree != null) {
cont = new Cont<>(tree, false, cont);
iterateDefCPS(tree.left, action, tree.right != null ? new Cont<>(tree.right, true, cont) : cont);
} else {
if (!cont.isRight) {
action.accept(cont.tree.content);
}
iterateDefCPS(cont.isRight ? cont.tree : null, action, cont.next);
}
}
static <T> void iterate(Tree<T> tree, Consumer<T> action, Cont<T> cont) {
while (tree != null || cont != null) {
if (tree != null) {
cont = new Cont<>(tree, false, cont);
cont = tree.right != null ? new Cont<>(tree.right, true, cont) : cont;
tree = tree.left;
} else {
if (!cont.isRight) {
action.accept(cont.tree.content);
tree = null;
} else {
tree = cont.tree;
}
cont = cont.next;
}
}
}
private Tree<T> tree;
private Cont<T> cont;
PostOrderIterator(Tree<T> tree) {
this.tree = tree;
}
@Override
public boolean hasNext() {
return tree != null || cont != null;
}
@Override
public T next() {
while (hasNext()) {
if (tree != null) {
cont = new Cont<>(tree, false, cont);
cont = tree.right != null ? new Cont<>(tree.right, true, cont) : cont;
tree = tree.left;
} else {
T content = null;
if (!cont.isRight) {
content = cont.tree.content;
tree = null;
} else {
tree = cont.tree;
}
cont = cont.next;
if (content != null) {
return content;
}
}
}
throw new NoSuchElementException();
}
}