[java] Java에서 트리 데이터 구조를 구현하는 방법은 무엇입니까? [닫은]

Java에서 트리를 나타내는 표준 Java 라이브러리 클래스가 있습니까?

특히 나는 다음을 대표해야합니다.

  • 모든 노드의 하위 트리는 임의의 수의 자식을 가질 수 있습니다
  • 각 노드 (루트 뒤)와 그 하위 노드는 문자열 값을 갖습니다.
  • 주어진 노드의 모든 자식 (일부 목록 또는 문자열 배열)을 가져와야하며 문자열 값입니다 (즉, 노드를 입력으로 사용하고 자식 노드의 모든 문자열 값을 출력으로 반환하는 메소드)

이것에 사용 가능한 구조가 있습니까? 아니면 직접 작성해야합니다 (구현 제안이 좋을 경우).



답변

여기:

public class Tree<T> {
    private Node<T> root;

    public Tree(T rootData) {
        root = new Node<T>();
        root.data = rootData;
        root.children = new ArrayList<Node<T>>();
    }

    public static class Node<T> {
        private T data;
        private Node<T> parent;
        private List<Node<T>> children;
    }
}

그것은 기본 트리 구조 String나 다른 객체에 사용될 수 있습니다 . 간단한 트리를 구현하여 필요한 작업을 수행하는 것은 매우 쉽습니다.

추가해야 할 것은 추가, 제거, 순회 및 생성자를위한 메소드입니다. 의 Node기본 빌딩 블록입니다 Tree.


답변

또 다른 트리 구조 :

public class TreeNode<T> implements Iterable<TreeNode<T>> {

    T data;
    TreeNode<T> parent;
    List<TreeNode<T>> children;

    public TreeNode(T data) {
        this.data = data;
        this.children = new LinkedList<TreeNode<T>>();
    }

    public TreeNode<T> addChild(T child) {
        TreeNode<T> childNode = new TreeNode<T>(child);
        childNode.parent = this;
        this.children.add(childNode);
        return childNode;
    }

    // other features ...

}

샘플 사용법 :

TreeNode<String> root = new TreeNode<String>("root");
{
    TreeNode<String> node0 = root.addChild("node0");
    TreeNode<String> node1 = root.addChild("node1");
    TreeNode<String> node2 = root.addChild("node2");
    {
        TreeNode<String> node20 = node2.addChild(null);
        TreeNode<String> node21 = node2.addChild("node21");
        {
            TreeNode<String> node210 = node20.addChild("node210");
        }
    }
}

보너스
다음과 같은 본격적인 나무를보십시오.

  • 반복자
  • 수색
  • 자바 / C #

https://github.com/gt4dev/yet-another-tree-structure


답변

실제로 JDK에는 꽤 좋은 트리 구조가 구현되어 있습니다.

javax.swing.tree , TreeModelTreeNode를 살펴보십시오 . 그것들은 함께 사용하도록 설계 JTreePanel되었지만 실제로는 꽤 좋은 트리 구현이며 스윙 인터페이스없이 사용하지 못하게하는 것은 없습니다.

Java 9부터는 ‘Compact profiles’에 존재하지 않으므로 이러한 클래스를 사용하지 않을 수 있습니다 .


답변

이건 어때?

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;

/**
  * @author ycoppel@google.com (Yohann Coppel)
  *
  * @param <T>
  *          Object's type in the tree.
*/
public class Tree<T> {

  private T head;

  private ArrayList<Tree<T>> leafs = new ArrayList<Tree<T>>();

  private Tree<T> parent = null;

  private HashMap<T, Tree<T>> locate = new HashMap<T, Tree<T>>();

  public Tree(T head) {
    this.head = head;
    locate.put(head, this);
  }

  public void addLeaf(T root, T leaf) {
    if (locate.containsKey(root)) {
      locate.get(root).addLeaf(leaf);
    } else {
      addLeaf(root).addLeaf(leaf);
    }
  }

  public Tree<T> addLeaf(T leaf) {
    Tree<T> t = new Tree<T>(leaf);
    leafs.add(t);
    t.parent = this;
    t.locate = this.locate;
    locate.put(leaf, t);
    return t;
  }

  public Tree<T> setAsParent(T parentRoot) {
    Tree<T> t = new Tree<T>(parentRoot);
    t.leafs.add(this);
    this.parent = t;
    t.locate = this.locate;
    t.locate.put(head, this);
    t.locate.put(parentRoot, t);
    return t;
  }

  public T getHead() {
    return head;
  }

  public Tree<T> getTree(T element) {
    return locate.get(element);
  }

  public Tree<T> getParent() {
    return parent;
  }

  public Collection<T> getSuccessors(T root) {
    Collection<T> successors = new ArrayList<T>();
    Tree<T> tree = getTree(root);
    if (null != tree) {
      for (Tree<T> leaf : tree.leafs) {
        successors.add(leaf.head);
      }
    }
    return successors;
  }

  public Collection<Tree<T>> getSubTrees() {
    return leafs;
  }

  public static <T> Collection<T> getSuccessors(T of, Collection<Tree<T>> in) {
    for (Tree<T> tree : in) {
      if (tree.locate.containsKey(of)) {
        return tree.getSuccessors(of);
      }
    }
    return new ArrayList<T>();
  }

  @Override
  public String toString() {
    return printTree(0);
  }

  private static final int indent = 2;

  private String printTree(int increment) {
    String s = "";
    String inc = "";
    for (int i = 0; i < increment; ++i) {
      inc = inc + " ";
    }
    s = inc + head;
    for (Tree<T> child : leafs) {
      s += "\n" + child.printTree(increment + indent);
    }
    return s;
  }
}


답변

내가 핸들 일반적인 나무 그 작은 라이브러리를. 스윙 물건보다 훨씬 가볍습니다. 또한 그것을위한 maven 프로젝트 가 있습니다.


답변

public class Tree {
    private List<Tree> leaves = new LinkedList<Tree>();
    private Tree parent = null;
    private String data;

    public Tree(String data, Tree parent) {
        this.data = data;
        this.parent = parent;
    }
}

분명히 하위를 추가 / 제거하는 유틸리티 메소드를 추가 할 수 있습니다.


답변

도메인을 위해 트리가 무엇인지 정의하는 것부터 시작해야합니다 . 먼저 인터페이스 를 정의하는 것이 가장 좋습니다 . 모든 트리 구조를 수정할 수있는 것은 아니며 노드 를 추가제거 할 수있는 기능은 선택적인 기능이므로 추가 인터페이스를 만들어야합니다.

값을 보유하는 노드 객체를 만들 필요가 없습니다 . 사실 이것은 대부분의 트리 구현에서 주요 디자인 결함과 오버 헤드로 간주됩니다. Swing을 보면 실제로 필요하지 않기 때문에 TreeModel노드 클래스가 없습니다 (만 DefaultTreeModel사용 TreeNode).

public interface Tree <N extends Serializable> extends Serializable {
    List<N> getRoots ();
    N getParent (N node);
    List<N> getChildren (N node);
}

가변 트리 구조 (노드 추가 및 제거 가능) :

public interface MutableTree <N extends Serializable> extends Tree<N> {
    boolean add (N parent, N node);
    boolean remove (N node, boolean cascade);
}

이러한 인터페이스가 주어지면 트리를 사용하는 코드는 트리가 어떻게 구현되는지에 대해 신경 쓸 필요가 없습니다. 이를 통해 일반 구현특수한 구현 을 사용할 수 있으며, 함수를 다른 API에 위임하여 트리를 실현할 수 있습니다.

예 : 파일 트리 구조

public class FileTree implements Tree<File> {

    @Override
    public List<File> getRoots() {
        return Arrays.stream(File.listRoots()).collect(Collectors.toList());
    }

    @Override
    public File getParent(File node) {
        return node.getParentFile();
    }

    @Override
    public List<File> getChildren(File node) {
        if (node.isDirectory()) {
            File[] children = node.listFiles();
            if (children != null) {
                return Arrays.stream(children).collect(Collectors.toList());
            }
        }
        return Collections.emptyList();
    }
}

예 : 일반 트리 구조 (부모 / 자식 관계 기반) :

public class MappedTreeStructure<N extends Serializable> implements MutableTree<N> {

    public static void main(String[] args) {

        MutableTree<String> tree = new MappedTreeStructure<>();
        tree.add("A", "B");
        tree.add("A", "C");
        tree.add("C", "D");
        tree.add("E", "A");
        System.out.println(tree);
    }

    private final Map<N, N> nodeParent = new HashMap<>();
    private final LinkedHashSet<N> nodeList = new LinkedHashSet<>();

    private void checkNotNull(N node, String parameterName) {
        if (node == null)
            throw new IllegalArgumentException(parameterName + " must not be null");
    }

    @Override
    public boolean add(N parent, N node) {
        checkNotNull(parent, "parent");
        checkNotNull(node, "node");

        // check for cycles
        N current = parent;
        do {
            if (node.equals(current)) {
                throw new IllegalArgumentException(" node must not be the same or an ancestor of the parent");
            }
        } while ((current = getParent(current)) != null);

        boolean added = nodeList.add(node);
        nodeList.add(parent);
        nodeParent.put(node, parent);
        return added;
    }

    @Override
    public boolean remove(N node, boolean cascade) {
        checkNotNull(node, "node");

        if (!nodeList.contains(node)) {
            return false;
        }
        if (cascade) {
            for (N child : getChildren(node)) {
                remove(child, true);
            }
        } else {
            for (N child : getChildren(node)) {
                nodeParent.remove(child);
            }
        }
        nodeList.remove(node);
        return true;
    }

    @Override
    public List<N> getRoots() {
        return getChildren(null);
    }

    @Override
    public N getParent(N node) {
        checkNotNull(node, "node");
        return nodeParent.get(node);
    }

    @Override
    public List<N> getChildren(N node) {
        List<N> children = new LinkedList<>();
        for (N n : nodeList) {
            N parent = nodeParent.get(n);
            if (node == null && parent == null) {
                children.add(n);
            } else if (node != null && parent != null && parent.equals(node)) {
                children.add(n);
            }
        }
        return children;
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        dumpNodeStructure(builder, null, "- ");
        return builder.toString();
    }

    private void dumpNodeStructure(StringBuilder builder, N node, String prefix) {
        if (node != null) {
            builder.append(prefix);
            builder.append(node.toString());
            builder.append('\n');
            prefix = "  " + prefix;
        }
        for (N child : getChildren(node)) {
            dumpNodeStructure(builder, child, prefix);
        }
    }
}