使用泛型类在Java中遍历树

时间:2014-06-25 23:56:47

标签: java oop generics interface tree-traversal

确切地说,我试图压扁一棵树,并且我一直试图使用泛型函数在泛型类中获取私有属性的值。

我已经附加了类来显示树的结构。但它看起来像这样:

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

我打算在最后粘贴我的尝试。首先,让我介绍一下这些课程:

Triple只存储三个相同类型的值。

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; }
}

直接的界面:

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

现在,对于一个棘手的课程。这个只是一种存储两种类型值的EitherOr的类型,但不能同时存储两种类型。

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;
    }
}

我知道这已经很久了,但请耐心等待。该类实现树结构。

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);
         }
    }
}

好的。这是我对扁平化的想法:

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;
    }
}

正如我所说,我一直试图使用Function接口检索EitherOr类中的值。我正在考虑实现Function接口并为&#34; apply&#34;编写一个函数。只是获得了价值,但我不知道该怎么做。任何帮助,将不胜感激。谢谢!

1 个答案:

答案 0 :(得分:3)

所以,这是你的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',如果它是“left”)

......和:

  • ifRightFunction会产生一系列元素(因为EitherOr<T, Triple<Tree<T>>>有一个T elems'列表,如果它是“正确的”)

现在让我们看看这些功能:

ifLeftFunction是......基本的。我想从...... T中提取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]


干杯;)