From 84161ab2edb057cc5f796cab8044f61ba431d229 Mon Sep 17 00:00:00 2001 From: Abhinav Sarkar Date: Wed, 17 Jul 2019 10:35:59 +0530 Subject: [PATCH] Adds tree iterators based on CPS defunctionalization --- .../abhinavsarkar/algorist/TreeIterators.java | 386 ++++++++++++++++++ 1 file changed, 386 insertions(+) create mode 100644 src/main/java/net/abhinavsarkar/algorist/TreeIterators.java diff --git a/src/main/java/net/abhinavsarkar/algorist/TreeIterators.java b/src/main/java/net/abhinavsarkar/algorist/TreeIterators.java new file mode 100644 index 0000000..68a124a --- /dev/null +++ b/src/main/java/net/abhinavsarkar/algorist/TreeIterators.java @@ -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 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 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 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 postOrderIterator = new PostOrderIterator<>(tree); + while (postOrderIterator.hasNext()) { + System.out.print(postOrderIterator.next()); + } + System.out.println("\tPostOrderIterator"); + } + +} + +class Tree { + Tree left; + T content; + Tree right; + + Tree(Tree left, T content, Tree right) { + this.left = left; + this.content = content; + this.right = right; + } + + @Override + public String toString() { + return content.toString(); + } +} + +class InOrderIterator implements Iterator { + + private static class Cont { + Tree tree; + Cont next; + + Cont(Tree tree, Cont next) { + this.tree = tree; + this.next = next; + } + } + + static void iterateRecursive(Tree tree, Consumer action) { + if (tree != null) { + iterateRecursive(tree.left, action); + action.accept(tree.content); + iterateRecursive(tree.right, action); + } + } + + static void iterateCPS(Tree tree, Consumer action, Runnable cont) { + if (tree != null) { + iterateCPS(tree.left, action, () -> { + action.accept(tree.content); + iterateCPS(tree.right, action, cont); + }); + } else { + cont.run(); + } + } + + static void iterateDefCPS(Tree tree, Consumer action, Cont 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 void iterate(Tree tree, Consumer action, Cont 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 tree; + private Cont cont; + + InOrderIterator(Tree 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 implements Iterator { + + private static class Cont { + Tree tree; + Cont next; + + Cont(Tree tree, Cont next) { + this.tree = tree; + this.next = next; + } + } + + static void iterateRecursive(Tree tree, Consumer action) { + if (tree != null) { + action.accept(tree.content); + iterateRecursive(tree.left, action); + iterateRecursive(tree.right, action); + } + } + + static void iterateCPS(Tree tree, Consumer action, Runnable cont) { + if (tree != null) { + action.accept(tree.content); + iterateCPS(tree.left, action, () -> iterateCPS(tree.right, action, cont)); + } else { + cont.run(); + } + } + + static void iterateDefCPS(Tree tree, Consumer action, Cont 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 void iterate(Tree tree, Consumer action, Cont 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 tree; + private Cont cont; + + PreOrderIterator(Tree 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 implements Iterator { + + static class Cont { + Tree tree; + boolean isRight; + Cont next; + + Cont(Tree tree, boolean isRight, Cont next) { + this.tree = tree; + this.next = next; + this.isRight = isRight; + } + } + + static void iterateRecursive(Tree tree, Consumer action) { + if (tree != null) { + iterateRecursive(tree.left, action); + iterateRecursive(tree.right, action); + action.accept(tree.content); + } + } + + static void iterateCPS(Tree tree, Consumer action, Runnable cont) { + if (tree != null) { + iterateCPS(tree.left, action, () -> iterateCPS(tree.right, action, () -> { + action.accept(tree.content); + cont.run(); + })); + } else { + cont.run(); + } + } + + + static void iterateDefCPS(Tree tree, Consumer action, Cont 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 void iterate(Tree tree, Consumer action, Cont 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 tree; + private Cont cont; + + PostOrderIterator(Tree 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(); + } + +} \ No newline at end of file