All Downloads are FREE. Search and download functionalities are using the official Maven repository.

xdean.jex.extra.collection.Traverse Maven / Gradle / Ivy

The newest version!
package xdean.jex.extra.collection;

import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Deque;
import java.util.Iterator;
import java.util.function.Function;

import io.reactivex.Flowable;
import xdean.jex.extra.rx2.RxIterator;

public class Traverse {
  @FunctionalInterface
  public interface Traversable extends Iterable {
    Flowable traverse(Traverser t);

    default Traverser defaultTraverser() {
      return DefaultTraverser.BREAD_FIRST;
    }

    @Override
    default Iterator iterator() {
      return iterator(defaultTraverser());
    }

    default Iterator iterator(Traverser traverser) {
      return traverse(traverser).to(RxIterator.flowableIterator());
    }

    default Flowable preOrderTraversal() {
      return traverse(DefaultTraverser.PRE_ORDER);
    }

    default Flowable postOrderTraversal() {
      return traverse(DefaultTraverser.POST_ORDER);
    }

    default Flowable breadthFirstTraversal() {
      return traverse(DefaultTraverser.BREAD_FIRST);
    }
  }

  @FunctionalInterface
  public interface Traverser {
     Flowable travese(T root, Function> getChildren);
  }

  public enum DefaultTraverser implements Traverser {
    PRE_ORDER(Traverse::preOrderTraversal),
    POST_ORDER(Traverse::postOrderTraversal),
    BREAD_FIRST(Traverse::breadthFirstTraversal);

    private final Traverser traverser;

    private DefaultTraverser(Traverser traverser) {
      this.traverser = traverser;
    }

    @Override
    public  Flowable travese(T root, Function> getChildren) {
      return traverser.travese(root, getChildren);
    }
  }

  private static  Deque newDeque(T root) {
    Deque deque = new ArrayDeque<>();
    deque.add(root);
    return deque;
  }

  public static  Flowable preOrderTraversal(T root, Function> getChildren) {
    return Flowable.generate(() -> newDeque(Arrays.asList(root).iterator()), (d, e) -> {
      Iterator iterator;
      while (true) {
        if (d.isEmpty()) {
          e.onComplete();
          return;
        }
        iterator = d.peek();
        if (iterator.hasNext()) {
          break;
        } else {
          d.pop();
        }
      }
      T t = iterator.next();
      e.onNext(t);
      Iterator children = getChildren.apply(t).iterator();
      if (children.hasNext()) {
        d.push(children);
      }
    });
  }

  public static  Flowable postOrderTraversal(T root, Function> getChildren) {
    return Flowable.generate(() -> newDeque(Either., T> left(Arrays.asList(root).iterator())), (d, e) -> {
      Either, T> item;
      while (true) {
        if (d.isEmpty()) {
          e.onComplete();
          return;
        }
        item = d.peek();
        item.exec(iterator -> {
          if (iterator.hasNext()) {
            T t = iterator.next();
            Iterator children = getChildren.apply(t).iterator();
            d.push(Either.right(t));
            if (children.hasNext()) {
              d.push(Either.left(children));
            }
          } else {
            d.pop();
          }
        }, value -> {
          d.pop();
          e.onNext(value);
        });
        if (item.isRight()) {
          return;
        }
      }
    });
  }

  public static  Flowable breadthFirstTraversal(T root, Function> getChildren) {
    return Flowable.generate(() -> newDeque(Arrays.asList(root).iterator()), (d, e) -> {
      Iterator iterator;
      while (true) {
        if (d.isEmpty()) {
          e.onComplete();
          return;
        }
        iterator = d.peek();
        if (iterator.hasNext()) {
          break;
        } else {
          d.pop();
        }
      }
      T t = iterator.next();
      e.onNext(t);
      Iterator children = getChildren.apply(t).iterator();
      if (children.hasNext()) {
        d.addLast(children);
      }
    });
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy