Javaでツリーデータ構造を実装する方法 [閉まっている]


496

Javaでツリーを表す標準のJavaライブラリクラスはありますか?

具体的には、以下を表す必要があります。

  • 任意のノードのサブツリーは、任意の数の子を持つことができます
  • 各ノード(ルートの後)とその子は文字列値を持ちます
  • 特定のノードのすべての子(ある種のリストまたは文字列の配列)とその文字列値(つまり、ノードを入力として受け取り、子ノードのすべての文字列値を出力として返すメソッド)を取得する必要があります。

これに利用できる構造はありますか、または自分で作成する必要がありますか?


3
Java 8を使用していて、ストリームやフィルタリングなどでノードをトラバースしたい場合。その後、Durianのgithub.com/diffplug/durianをご覧になることをお勧めします
Ned Twigg

1
このAPIを使用できます:sourceforge.net/p/treeds4j
Mohamed Ennahdi El Idrissi '20

回答:


306

ここに:

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


304
厳密に言えば、TreeクラスNode自体は必要ありません。クラス自体は、それ自体がツリーと見なすことができるためです。
Joachim Sauer

34
@Joa、私はルートを含む構造が好きです。単一ノードではなくツリーを呼び出す方が理にかなっているメソッドをツリークラスに追加できます。
jjnguy 2010

24
@ジャスティン:例えば?それは正直な質問です。サブツリーでは意味をなさないツリー全体で意味のある単一のメソッドを考えることはできません。
Joachim Sauer、

22
Treeクラスは必要ないということで、@ Joaに同意します。個別のTreeクラスを追加せず、Nodeクラスを一貫して使用することで、コードの中でツリーの再帰的な性質を明示的に残したいと思います。代わりに、ツリーのルートノードを処理していることを明確にする必要がある場合は、変数に「ツリー」または「ルート」と名前を付けます。
jvdbogae

89
@Joa 4歳の私はあなたに完全に同意します。ツリークラスをNixします。
jjnguy 14

122

さらに別のツリー構造:

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

ボーナス
:本格的なツリーを参照してください:

  • イテレータ
  • 探す
  • Java / C#

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


2
あなたのライブラリが非常に便利であることがわかりました。ありがとうございました。しかし、親子間の参照関係に基づいてツリー構造を動的に生成する方法を知りたいのですが。与えられた例は、1つのメンバー1が別のメンバー2をスポンサーし、メンバー2がメンバー3をスポンサーする、などです。すでにテーブルレコードの関係がありますが、ライブラリを使用してそれらをツリーに入力できるかどうか不明です。
d4v1dv00 2015

1
2016年現在、リンクにはソースファイルやダウンロードが含まれていません
Sharon Ben Asher

2
私の見解では、この回答は、上記のより高い評価の回答から3年後の方が、よりクリーンな回答です。ただし、this.childrenのLinkedListをArrayListに置き換えます。
HopeKing 2017年

1
子供にはセットを使います。
DPM

私は間違っている可能性がありますが、この実装では、有効な結果を得るためhasNext()next()を呼び出す前にを呼び出す必要があるようです。これはIterator仕様の一部ではありません。
ロバート・ルイス

97

実際、JDKにはかなり良いツリー構造が実装されています。

javax.swing.treeTreeModel、およびTreeNodeを見てください。彼らはで使用するように設計されていますJTreePanelが、実際には非常に優れたツリー実装であり、swingインターフェースなしで使用することを妨げるものは何もありません。

Java 9以降では、これらのクラスは「コンパクトプロファイル」に存在しないため、使用しない方がよい場合があります


5
ええ、私は過去にそれらを使用しました、そして彼らはあなたが木から望むすべてをします。私が考えることができる唯一の欠点は、それぞれの実装クラス(DefaultTreeModelおよびDefaultMutableTreeNode)の名前の長さです。冗長ですが、それだけではないと思います。
Ultimate Gobblement 2010

4
これに対処する良い方法は、いくつかの静的メソッドnewModel()とnewNode()を作成し、それらを静的インポートすることです。
Gareth Davisが

140
Swingに関連しない関数でSwingライブラリを使用することは避けます。これは悪いコーディング習慣です。Swingがツリーをどのように実装するか、依存関係は何か、これが将来どのように変化するかは、決してわかりません。Swingはユーティリティライブラリではなく、UIライブラリです。
jasop

44
悪いコーディングの練習は少し厳しいと思います。
Gareth Davis

51
javax.swing.tree.TreeModelはパブリックインターフェース(java.util.Listとまったく同じ)であり、互換性のない変更はありません。追加の利点は、開発中にツリーを簡単にデバッグ/視覚化できることです。
lbalazscs 2012

45

これはどうですか?

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

5
このクラスオブジェクトを使用して作成されたツリーにDFSはどのように実装されますか?
leba-lev

3
このクラスを使用して葉の削除を実装するにはどうすればよいですか?
ゲダ2012

2
ヘッドフィールドは何に使用されますか?
Acour83 2014

2
このクラスにいくつかのドキュメントがあればすばらしいでしょう。私はかなりのようなメソッドが何を理解していないsetAsParentgetHeadん、これは私が実際にツリーデータ構造上のいくつかの助けを得ることができる時間です。ドキュメントの元のソースでさえ、コメントはありません。
障害者の

23

一般的なツリーを処理する小さなライブラリを書きました。スイングのものよりもはるかに軽量です。私はmavenプロジェクトも持っていますます。


3
私は今それを使っています、見事に動作します。私自身のカスタマイズのためにソースを大幅に変更する必要がありましたが、それは素晴らしい出発点でした。おかげでビビン!
jasop

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

明らかに、子を追加/削除するユーティリティメソッドを追加できます。


1
これは、ツリーの親がツリーであることを示唆しています。Tree Nodeクラスを作成しようとしていたと思います。
Madhur Bhargava

16

(ドメインの)ツリーが何であるかを定義することから始める必要があります。これは、最初にインターフェースを定義することで行うのが最善です。すべてのツリー構造が変更可能であるわけではありません。ノードを追加および削除できることはオプション機能であるため、そのための追加のインターフェースを作成します。

値を保持するノードオブジェクトを作成する必要はありません。実際、これはほとんどのツリー実装における主要な設計上の欠陥とオーバーヘッドであると考えています。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);
        }
    }
}

1
tree.add( "A"、 "B");を実行するときにこの構造に従うと問題が発生します。tree.add( "A"、 "C"); tree.add( "C"、 "D"); tree.add( "E"、 "A"); EはAの親です。これを行うにはどうすればよいですか?
saNiks

1
こんにちはsaNicks。上記のコードにバグがあり、最後の関係が追加されませんでした。現在は修正されており、null以外のチェックと(より重要な)を追加しました。ツリー構造の違反を防ぐ循環チェック(コードまたはその祖先の1つを自分自身に追加する)です。ヒントをありがとう!
Peter Walser

1
誰かがそのバグの修正を探している場合は、バグを修正しました。あなたがしなければならないことは、addメソッドがfalseを返すかどうかを確認し、それがfalseの場合、一時的に新しいLinkedHashSet <N>を作成し、ツリーのノードリストをそこに複製すると、uをクリアできます。ツリー、前の手順で追加されなかった親ノードを追加してから、tempNodeのaddAllを親ツリーに戻します。ただし、構造に感謝します。
saNiks

2
それらの不要なパブリック修飾子をインターフェースから削除するだけです。
Hamedz

1
これからjson配列を生成する方法
Pawan Pandey

12

単純化しすぎて機能しているコードについては回答がないため、ここに示します。

public class TreeNodeArray<T> {
    public T value;
    public final  java.util.List<TreeNodeArray<T>> kids =  new java.util.ArrayList<TreeNodeArray<T>>();
}


8

ホワイトボードのコーディング、インタビュー、または単にツリーの使用を計画している場合、これらの冗長性はすべて少しです。

さらに、ツリーがそこにない理由は、たとえばa Pair(同じことが言えるかもしれません)は、それを使用してクラスにデータをカプセル化する必要があり、最も単純な実装が次のようになるためです。

/***
/* Within the class that's using a binary tree for any reason. You could 
/* generalize with generics IFF the parent class needs different value types.
 */
private class Node {
  public String value;
  public Node[] nodes; // Or an Iterable<Node> nodes;
}

実際には、任意の幅のツリーについてはこれで終わりです。

バイナリツリーが必要な場合は、多くの場合、名前付きフィールドを使用する方が簡単です。

private class Node { // Using package visibility is an option
  String value;
  Node left;
  Node right;
}

または、トライが必要な場合:

private class Node {
  String value;
  Map<char, Node> nodes;
}

今あなたはあなたが欲しいと言いました

特定のノードを表す入力文字列を指定して、すべての子(ある種のリストまたは文字列の配列)を取得できるようにする

宿題のようですね。
しかし、締め切りが過ぎたと私は合理的に確信しているので…

import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;

public class kidsOfMatchTheseDays {
 static private class Node {
   String value;
   Node[] nodes;
 }

 // Pre-order; you didn't specify.
 static public List<String> list(Node node, String find) {
   return list(node, find, new ArrayList<String>(), false);
 }

 static private ArrayList<String> list(
     Node node,
     String find,
     ArrayList<String> list,
     boolean add) {
   if (node == null) {
     return list;
   }
   if (node.value.equals(find)) {
     add = true;
   }
   if (add) {
     list.add(node.value);
   }
   if (node.nodes != null) {
     for (Node child: node.nodes) {
       list(child, find, list, add);
     }
   }
   return list;
 }

 public static final void main(String... args) {
   // Usually never have to do setup like this, so excuse the style
   // And it could be cleaner by adding a constructor like:
   //     Node(String val, Node... children) {
   //         value = val;
   //         nodes = children;
   //     }
   Node tree = new Node();
   tree.value = "root";
   Node[] n = {new Node(), new Node()};
   tree.nodes = n;
   tree.nodes[0].value = "leftish";
   tree.nodes[1].value = "rightish-leafy";
   Node[] nn = {new Node()};
   tree.nodes[0].nodes = nn;
   tree.nodes[0].nodes[0].value = "off-leftish-leaf";
   // Enough setup
   System.out.println(Arrays.toString(list(tree, args[0]).toArray()));
 }
}

これにより、次のように使用できます。

$ java kidsOfMatchTheseDays leftish
[leftish, off-leftish-leaf]
$ java kidsOfMatchTheseDays root
[root, leftish, off-leftish-leaf, rightish-leafy]
$ java kidsOfMatchTheseDays rightish-leafy
[rightish-leafy]
$ java kidsOfMatchTheseDays a
[]

7

Garethの回答と同じように、DefaultMutableTreeNodeを確認してください。それは一般的ではありませんが、それ以外は法案に合うようです。javax.swingパッケージに含まれていますが、AWTクラスやSwingクラスに依存していません。実際、ソースコードには実際にコメントがあります// ISSUE: this class depends on nothing in AWT -- move to java.util?


笑、どうやってこのクラスに出くわしたの?
パセリエ

7

Javaには、JDK SwingのDefaultMutableTreeNode、StanfordパーサーパッケージのTree、その他のおもちゃのコードなど、いくつかのツリーデータ構造があります。しかし、これらはどれも十分ではありませんが、一般的な目的には十分に小さくありません。

Javaツリープロジェクトは、Javaで別の汎用ツリーデータ構造を提供しようとします。これと他の違いは

  • 完全に無料です。あなたはそれをどこでも使用できます(宿題を除いて:P)
  • 小さいですが一般的です。データ構造のすべてを1つのクラスファイルに入れているので、簡単にコピー/貼り付けできます。
  • おもちゃだけではありません。バイナリツリーまたは制限された操作のみを処理できる数十のJavaツリーコードを知っています。このTreeNodeはそれ以上のものです。これは、プレオーダー、ポストオーダー、幅優先、リーフ、ルートへのパスなど、ノードを訪問するさまざまな方法を提供します。さらに、イテレータも十分に提供されます。
  • その他のユーティリティが追加されます。特にgithub経由でリクエストを送信する場合は特に、このプロジェクトを包括的にするためにさらに操作を追加したいと思います。


5

質問は利用可能なデータ構造を要求するため、ツリーはリストまたは配列から構築できます。

Object[] tree = new Object[2];
tree[0] = "Hello";
{
  Object[] subtree = new Object[2];
  subtree[0] = "Goodbye";
  subtree[1] = "";
  tree[1] = subtree;
}

instanceof 要素がサブツリーかターミナルノードかを判断するために使用できます。


2
かなり醜い。データオブジェクトが配列またはリストの場合、機能しません。
user686249

1
私はそれが醜いことに同意します。ObjectSはいずれかのリーフオブジェクト(例えば、あろうStringS)または分岐(配列によって表されます)。そして、それは機能します:そのコードはコンパイルされ、の小さなツリーを作成しますString
Olathe 2016年

5
public abstract class Node {
  List<Node> children;

  public List<Node> getChidren() {
    if (children == null) {
      children = new ArrayList<>();
    }
    return chidren;
  }
}

とてもシンプルで使いやすいです。それを使用するには、それを拡張します。

public class MenuItem extends Node {
  String label;
  String href;
  ...
}

3

例えば ​​:

import java.util.ArrayList;
import java.util.List;



/**
 * 
 * @author X2
 *
 * @param <T>
 */
public class HisTree<T> 
{
    private Node<T> root;

    public HisTree(T rootData) 
    {
        root = new Node<T>();
        root.setData(rootData);
        root.setChildren(new ArrayList<Node<T>>());
    }

}

class Node<T> 
{

    private T data;
    private Node<T> parent;
    private List<Node<T>> children;

    public T getData() {
        return data;
    }
    public void setData(T data) {
        this.data = data;
    }
    public Node<T> getParent() {
        return parent;
    }
    public void setParent(Node<T> parent) {
        this.parent = parent;
    }
    public List<Node<T>> getChildren() {
        return children;
    }
    public void setChildren(List<Node<T>> children) {
        this.children = children;
    }
}

3

これまでは、ネストされたマップを使用していました。これは私が今日使用しているもので、非常にシンプルですが私のニーズに合います。多分これは別のものを助けるでしょう。

import com.fasterxml.jackson.annotation.JsonValue;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

/**
 * Created by kic on 16.07.15.
 */
public class NestedMap<K, V> {
    private final Map root = new HashMap<>();

    public NestedMap<K, V> put(K key) {
        Object nested = root.get(key);

        if (nested == null || !(nested instanceof NestedMap)) root.put(key, nested = new NestedMap<>());
        return (NestedMap<K, V>) nested;
    }

    public Map.Entry<K,V > put(K key, V value) {
        root.put(key, value);

        return (Map.Entry<K, V>) root.entrySet().stream().filter(e -> ((Map.Entry) e).getKey().equals(key)).findFirst().get();
    }

    public NestedMap<K, V> get(K key) {
        return (NestedMap<K, V>) root.get(key);
    }

    public V getValue(K key) {
        return (V) root.get(key);
    }

    @JsonValue
    public Map getRoot() {
        return root;
    }

    public static void main(String[] args) throws Exception {
        NestedMap<String, Integer> test = new NestedMap<>();
        test.put("a").put("b").put("c", 12);
        Map.Entry<String, Integer> foo = test.put("a").put("b").put("d", 12);
        test.put("b", 14);
        ObjectMapper mapper = new ObjectMapper();
        System.out.println(mapper.writeValueAsString(test));

        foo.setValue(99);
        System.out.println(mapper.writeValueAsString(test));

        System.out.println(test.get("a").get("b").getValue("d"));
    }
}

3

パスの追加をサポートする「HashMap」に基づく小さな「TreeMap」クラスを書きました。

import java.util.HashMap;
import java.util.LinkedList;

public class TreeMap<T> extends LinkedHashMap<T, TreeMap<T>> {

    public void put(T[] path) {
        LinkedList<T> list = new LinkedList<>();
        for (T key : path) {
            list.add(key);
        }
        return put(list);
    }

    public void put(LinkedList<T> path) {
        if (path.isEmpty()) {
            return;
        }
        T key = path.removeFirst();
        TreeMap<T> val = get(key);
        if (val == null) {
            val = new TreeMap<>();
            put(key, val);
        }
        val.put(path);
    }

}

これは、タイプ「T」(汎用)のツリーを格納するために使用できますが、そのノードへの追加データの格納は(まだ)サポートしていません。次のようなファイルがある場合:

root, child 1
root, child 1, child 1a
root, child 1, child 1b
root, child 2
root, child 3, child 3a

次に、次のコマンドを実行してツリーにすることができます。

TreeMap<String> root = new TreeMap<>();
Scanner scanner = new Scanner(new File("input.txt"));
while (scanner.hasNextLine()) {
  root.put(scanner.nextLine().split(", "));
}

そして、あなたは素敵な木を手に入れます。ニーズに合わせて簡単に調整できる必要があります。


2

Jakarta Projectの一部であるApache JMeterに含まれているHashTreeクラスを使用できます。

HashTreeクラスは、パッケージorg.apache.jorphan.collectionsに含まれています。このパッケージはJMeterプロジェクトの外ではリリースされていませんが、簡単に入手できます。

1)JMeterソースをダウンロードする

2)新しいパッケージを作成します。

3)/ src / jorphan / org / apache / jorphan / collections /にコピーします。Data.javaを除くすべてのファイル

4)/src/jorphan/org/apache/jorphan/util/JOrphanUtils.javaもコピーします

5)HashTreeを使用する準備が整いました。


2

Javaには、要件に合う特定のデータ構造はありません。要件は非常に具体的であり、そのために独自のデータ構造を設計する必要があります。要件を見ると、特定の機能を備えたある種のn進ツリーが必要だと誰もが言うことができます。次の方法でデータ構造を設計できます。

  1. ツリーのノードの構造は、ノードのコンテンツや子のリストのようになります。子のリスト;}
  2. 指定された文字列の子を取得する必要があるため、2つのメソッドを使用できます。1ノード検索ノード(文字列str)は、指定された入力と同じ値を持つノードを返します(検索にBFSを使用)2:リストgetChildren(文字列str):このメソッドは内部的にsearchNodeを呼び出して同じ文字列を持つノードを取得し、次に子のすべての文字列値のリストを作成して戻ります。
  3. また、ツリーに文字列を挿入する必要があります。void insert(String parent、String value)というメソッドを1つ記述する必要があります。これにより、親と等しい値を持つノードが再び検索され、指定された値でノードを作成して、見つかった親の子のリストに追加できます。 。

Class Node {String value;のような1つのクラスでノードの構造を書くことをお勧めします。List children;}、およびsearch、insert、getChildrenなどの他のすべてのメソッドを別のNodeUtilsクラスに追加すると、ツリーのルートを渡して、次のような特定のツリーで操作を実行することもできます:class NodeUtils {public static Node search(Node root、String value) {// BFSを実行してノードを返す}


2
    // TestTree.java
// A simple test to see how we can build a tree and populate it
//
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.tree.*;

public class TestTree extends JFrame {

  JTree tree;
  DefaultTreeModel treeModel;

  public TestTree( ) {
    super("Tree Test Example");
    setSize(400, 300);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
  }

  public void init( ) {
    // Build up a bunch of TreeNodes. We use DefaultMutableTreeNode because the
    // DefaultTreeModel can use it to build a complete tree.
    DefaultMutableTreeNode root = new DefaultMutableTreeNode("Root");
    DefaultMutableTreeNode subroot = new DefaultMutableTreeNode("SubRoot");
    DefaultMutableTreeNode leaf1 = new DefaultMutableTreeNode("Leaf 1");
    DefaultMutableTreeNode leaf2 = new DefaultMutableTreeNode("Leaf 2");

    // Build our tree model starting at the root node, and then make a JTree out
    // of it.
    treeModel = new DefaultTreeModel(root);
    tree = new JTree(treeModel);

    // Build the tree up from the nodes we created.
    treeModel.insertNodeInto(subroot, root, 0);
    // Or, more succinctly:
    subroot.add(leaf1);
    root.add(leaf2);

    // Display it.
    getContentPane( ).add(tree, BorderLayout.CENTER);
  }

  public static void main(String args[]) {
    TestTree tt = new TestTree( );
    tt.init( );
    tt.setVisible(true);
  }
}

3
コードを単にダンプするのではなく、それが何をするか、特に他のすべての回答と異なる理由(優れている)を説明してください。
Jan Doggen

2

私はJava8でうまく動作し、他の依存関係がないツリーライブラリを作成しました。また、関数型プログラミングからのアイデアの緩やかな解釈を提供し、ツリー全体またはサブツリーをマップ/フィルター/プルーニング/検索できます。

https://github.com/RutledgePaulV/prune

実装はインデックス作成に関して特別なことは何もせず、再帰から逸脱していなかったため、大きなツリーではパフォーマンスが低下し、スタックを爆破する可能性があります。しかし、必要なのは、深さが小から中程度の単純なツリーであれば、十分に機能すると思います。それは等号の正気な(値ベースの)定義を提供し、ツリーを視覚化できるtoString実装も持っています!


1

Collectionクラスを使用せずに、Treeデータ構造を使用した以下のコードを確認してください。コードにはバグ/改善があるかもしれませんが、参考のためにこれを使用してください

package com.datastructure.tree;

public class BinaryTreeWithoutRecursion <T> {

    private TreeNode<T> root;


    public BinaryTreeWithoutRecursion (){
        root = null;
    }


    public void insert(T data){
        root =insert(root, data);

    }

    public TreeNode<T>  insert(TreeNode<T> node, T data ){

        TreeNode<T> newNode = new TreeNode<>();
        newNode.data = data;
        newNode.right = newNode.left = null;

        if(node==null){
            node = newNode;
            return node;
        }
        Queue<TreeNode<T>> queue = new Queue<TreeNode<T>>();
        queue.enque(node);
        while(!queue.isEmpty()){

            TreeNode<T> temp= queue.deque();
            if(temp.left!=null){
                queue.enque(temp.left);
            }else
            {
                temp.left = newNode;

                queue =null;
                return node;
            }
            if(temp.right!=null){
                queue.enque(temp.right);
            }else
            {
                temp.right = newNode;
                queue =null;
                return node;
            }
        }
        queue=null;
        return node; 


    }

    public void inOrderPrint(TreeNode<T> root){
        if(root!=null){

            inOrderPrint(root.left);
            System.out.println(root.data);
            inOrderPrint(root.right);
        }

    }

    public void postOrderPrint(TreeNode<T> root){
        if(root!=null){

            postOrderPrint(root.left);

            postOrderPrint(root.right);
            System.out.println(root.data);
        }

    }

    public void preOrderPrint(){
        preOrderPrint(root);
    }


    public void inOrderPrint(){
        inOrderPrint(root);
    }

    public void postOrderPrint(){
        inOrderPrint(root);
    }


    public void preOrderPrint(TreeNode<T> root){
        if(root!=null){
            System.out.println(root.data);
            preOrderPrint(root.left);
            preOrderPrint(root.right);
        }

    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        BinaryTreeWithoutRecursion <Integer> ls=  new BinaryTreeWithoutRecursion <>();
        ls.insert(1);
        ls.insert(2);
        ls.insert(3);
        ls.insert(4);
        ls.insert(5);
        ls.insert(6);
        ls.insert(7);
        //ls.preOrderPrint();
        ls.inOrderPrint();
        //ls.postOrderPrint();

    }

}

2
コレクションクラスを使用せずに」では、Queueクラスはどこから来たのでしょうか。上記のように、これはバイナリツリーであり、最初の要件(任意の数の子ノード)で失敗します。
PhiLho 2014

1

java.util。*でTreeSetクラスを使用できます。バイナリ検索ツリーのように機能するため、すでにソートされています。TreeSetクラスは、Iterable、Collection、およびSetインターフェースを実装します。セットのようにイテレータを使用してツリーをトラバースできます。

TreeSet<String> treeSet = new TreeSet<String>();
Iterator<String> it  = treeSet.Iterator();
while(it.hasNext()){
...
}

あなたは、Java Doc他のいくつかをチェックすることができます。


-1

コレクションフレームワークを使用しないツリーのカスタムツリー実装。Treeの実装に必要なさまざまな基本的な操作が含まれています。

class Node {

    int data;
    Node left;
    Node right;

    public Node(int ddata, Node left, Node right) {
        this.data = ddata;
        this.left = null;
        this.right = null;      
    }

    public void displayNode(Node n) {
        System.out.print(n.data + " "); 
    }

}

class BinaryTree {

    Node root;

    public BinaryTree() {
        this.root = null;
    }

    public void insertLeft(int parent, int leftvalue ) {
        Node n = find(root, parent);
        Node leftchild = new Node(leftvalue, null, null);
        n.left = leftchild;
    }

    public void insertRight(int parent, int rightvalue) {
        Node n = find(root, parent);
        Node rightchild = new Node(rightvalue, null, null);
        n.right = rightchild;
    }

    public void insertRoot(int data) {
        root = new Node(data, null, null);
    }

    public Node getRoot() {
        return root;
    }

    public Node find(Node n, int key) {     
        Node result = null;

        if (n == null)
            return null;

        if (n.data == key)
            return n;

        if (n.left != null)
            result = find(n.left, key);

        if (result == null)
            result = find(n.right, key);

        return result;
    } 

    public int getheight(Node root){
        if (root == null)
            return 0;

        return Math.max(getheight(root.left), getheight(root.right)) + 1; 
    }

    public void printTree(Node n) {     
        if (n == null)
            return;

        printTree(n.left);
        n.displayNode(n);
        printTree(n.right);             
    }

}

11
これはバイナリツリーです
。OPの
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.