Java tree traversal using common classes

To be precise, I'm trying to smooth a tree, and I'm stuck trying to get the values ​​of private attributes in a generic class using a generic function.

I attached classes to show how the tree is structured accurately. But it looks something like this:

  /|\
 1 | 6
  /|\
 5 4 9

I am going to insert my attempt at the end. First, let me introduce the classes:

Triple simply stores three values ​​of the same type.

public class Triple<V> {
    private final V l, m, r;
    public Triple(V l, V m, V r) {
        this.l = l;
        this.m = m;
        this.r = r;
    }
    public V left()   { return l; }
    public V middle() { return m; }
    public V right()  { return r; }
}

Simple interface:

public interface Function<P, R> {
     R apply(P p);
}

Now for a complex class. It is just a type that stores one of the EitherOr of two types of values, but not both.

public class EitherOr<A,B> {
    // Constructs a left-type EitherOr
    public static <A> EitherOr left(A a) {
         return new EitherOr(a, null);
    }
    // Constructs a right-type EitherOr
    public static <B> EitherOr right(B b) {
         return new EitherOr(null, b);
    }
    private final A a;
    private final B b;

    private EitherOr(A a, B b) {
         this.a = a; this.b = b;
    }

    public<T> T ifLeft(Function<A,T> f) {
        return f.apply(a);
    }

public<T> T ifRight(Function<B,T> f) {
        return f.apply(b);
    }

    public boolean isLeft() {
        return b == null;
    }
}

I know this is dragging on, but the bear is with me. This class implements a tree structure.

public interface Tree<T> {
    EitherOr<T, Triple<Tree<T>>> get();

    static final class Leaf<T> implements Tree<T> {
           public static <T> Leaf<T> leaf (T value) {
                return new Leaf<T>(value);
           }

           private final T t;

           public Leaf(T t) { this.t = t; }

           @Override
           public EitherOr<T, Triple<Tree<T>>> get() {
                 return EitherOr.left(t);
           }
    }

    static final class Node<T> implements Tree<T> {
         public static <T> Tree<T> tree (T left, T middle, T right) {
             return new Node<T>(Leaf.leaf(left), Leaf.leaf(middle), Leaf.leaf(right));
     }

         private final Triple<Tree<T>> branches;

         public Node(Tree<T> left, Tree<T> middle, Tree<T> right) {
               this.branches = new Triple<Tree<T>>(left, middle, right);
         }

         @Override
         public EitherOr<T, Triple<Tree<T>>> get() {
                 return EitherOr.right(branches);
         }
    }
}

Good. Here is my smoothing idea:

public class MyFlattenTree<T> implements FlattenTree<T> {
    public List<T> flattenInOrder(Tree<T> tree) {
          List<T> list = new ArrayList<T>();
          EitherOr<T, Triple<Tree<T>>> EitherOr;
          EitherOr = tree.get();
          // it is a leaf
          if (EitherOr.isLeft()) {
               // This is where the problem lies
               // I don't how to get the value using a function f
               list.add((T) EitherOr.ifLeft(f));
               return list;
          }
          else {
               // basically recursively go through the tree somehow
          }
          return null;
    }
}

, EitherOr, Function. Function "apply", , , . . !

+4
1

, flattenInOrder:

public List<T> flattenInOrder(final Tree<T> tree) {
    final EitherOr<T, Triple<Tree<T>>> EitherOr = tree.get();
    if (EitherOr.isLeft()) {
        return Collections.singletonList(EitherOr.ifLeft(this.ifLeftFunction));
    }

    return EitherOr.ifRight(this.ifRightFunction);
}

, , :

  • ifLeftFunction ( EitherOr<T, Triple<Tree<T>>> T elem ', s "left" )

... :

  • ifRightFunction ( EitherOr<T, Triple<Tree<T>>> T elems ', "" )

:

ifLeftFunction ... . T ... a T.

final Function<T, T> ifLeftFunction = new Function<T, T>() {

    @Override
    public T apply(final T t) {
        return t;
    }
};

ifRightFunction : T , :

final Function<Triple<Tree<T>>, List<T>> ifRightFunction = new Function<Triple<Tree<T>>, List<T>>() {

    @Override
    public List<T> apply(final Triple<Tree<T>> t) {
        final List<T> res = new ArrayList<>();
        res.addAll(MyFlattenTree.this.flattenInOrder(t.left()));
        res.addAll(MyFlattenTree.this.flattenInOrder(t.middle()));
        res.addAll(MyFlattenTree.this.flattenInOrder(t.right()));
        return res;
    }
};

... !


:

public class MyFlattenTree<T> {

    private final Function<Triple<Tree<T>>, List<T>> ifRightFunction = new Function<Triple<Tree<T>>, List<T>>() {

        @Override
        public List<T> apply(final Triple<Tree<T>> t) {
            final List<T> res = new ArrayList<>();
            res.addAll(MyFlattenTree.this.flattenInOrder(t.left()));
            res.addAll(MyFlattenTree.this.flattenInOrder(t.middle()));
            res.addAll(MyFlattenTree.this.flattenInOrder(t.right()));
            return res;
        }
    };

    private final Function<T, T> ifLeftFunction = new Function<T, T>() {

        @Override
        public T apply(final T t) {
            return t;
        }
    };

    public static void main(final String[] args) {
        final Tree<String> tree = new Node<>(new Leaf<>("1"), new Node<>(new Leaf<>("5"), new Leaf<>("4"), new Leaf<>("9")), new Leaf<>("6"));
        System.out.println(new MyFlattenTree<String>().flattenInOrder(tree));
    }

    public List<T> flattenInOrder(final Tree<T> tree) {
        final EitherOr<T, Triple<Tree<T>>> EitherOr = tree.get();
        if (EitherOr.isLeft()) {
            return Collections.singletonList(EitherOr.ifLeft(this.ifLeftFunction));
        }

        return EitherOr.ifRight(this.ifRightFunction);
    }
}

, Tree, main :

public static void main(final String[] args) {
    final Tree<String> tree = new Node<>(new Leaf<>("1"), new Node<>(new Leaf<>("5"), new Leaf<>("4"), new Leaf<>("9")), new Leaf<>("6"));
    System.out.println(new MyFlattenTree<String>().flattenInOrder(tree));
}

: [1, 5, 4, 9, 6]


;)

+3

Source: https://habr.com/ru/post/1546071/


All Articles