Java树数据结构?

Java tree data-structure?

有一个好的可用(标准Java)数据结构来表示Java中的树吗?

具体来说,我需要代表以下内容:

  • 任何节点上的树都可以有任意数量的子级
  • 每个节点(在根之后)只是一个字符串(其子节点也是字符串)
  • 我需要能够让所有的子节点(某种列表或字符串数组)都得到一个表示给定节点的输入字符串。

是否有可用的结构来解决这个问题,或者我是否需要创建自己的结构(如果是这样的话,实现建议会很好)。


在这里:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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或任何其他对象。实现简单的树来做您需要的事情是相当容易的。

您需要添加的只是用于添加到、移除、遍历和构造函数的方法。NodeTree的基本组成部分。


还有另一种树结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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 ...

}

样品使用情况:

1
2
3
4
5
6
7
8
9
10
11
12
13
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、treemodel和treenode。它们被设计为与JTreePanel一起使用,但实际上,它们是一个非常好的树实现,并且没有什么能阻止您在没有Swing接口的情况下使用它。

注意,对于Java 9,您可能不希望使用这些类,因为它们将不存在于"紧凑配置文件"中。


这个怎么样?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;

/**
  * @author [email protected] (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 +="
"
+ child.printTree(increment + indent);
    }
    return s;
  }
}


我写了一个处理普通树的小库。它比秋千轻得多。我也有一个Maven项目。


1
2
3
4
5
6
7
8
9
10
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,因为它们不是真正需要的。

1
2
3
4
5
public interface Tree <N extends Serializable> extends Serializable {
    List<N> getRoots ();
    N getParent (N node);
    List<N> getChildren (N node);
}

可变树结构(允许添加和删除节点):

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

考虑到这些接口,使用树的代码不必太关心树是如何实现的。这允许您使用通用实现和专用实现,通过将函数委托给另一个API来实现树。

示例:文件树结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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();
    }
}

示例:通用树结构(基于父/子关系):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
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('
'
);
            prefix =" " + prefix;
        }
        for (N child : getChildren(node)) {
            dumpNodeStructure(builder, child, prefix);
        }
    }
}


没有答案提到过简化的工作代码,所以这里是:

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

您可以使用Java的任何XML API作为文档和节点,因为XML是一个带字符串的树结构。


在Java中有一些树数据结构,例如JDK Swing中的Debug ToMababeleReNoDE、斯坦福解析器包中的树和其他玩具代码。但这些都不足以满足一般用途。

Java树项目试图在Java中提供另一种通用树数据结构。这个和其他的区别是

  • 完全免费。你可以在任何地方使用它(家庭作业除外:p)
  • 小而一般。我将数据结构的所有内容都放在一个类文件中,这样就很容易复制/粘贴。
  • 不仅仅是玩具。我知道几十个Java树代码,只能处理二叉树或有限的操作。这棵树结比那要多得多。它提供了不同的访问节点的方法,如预排序、后排序、breadthfirst、leaves、根路径等,并且还提供了迭代器以充分利用这些方法。
  • 将添加更多的实用程序。我愿意增加更多的操作来使这个项目更全面,特别是如果你通过GitHub发送一个请求。


按照加雷斯的回答,查看默认可变树型。它不是通用的,但在其他方面似乎符合这个要求。即使它在javax.swing包中,它也不依赖于任何awt或swing类。实际上,源代码实际上有注释// ISSUE: this class depends on nothing in AWT -- move to java.util?


如果你在做白板编码,面试,甚至只是打算用一棵树,这些都有点冗长。

还应该说,树不在其中的原因,比如说,Pair(可以这样说),是因为您应该使用它将数据封装在类中,最简单的实现如下:

1
2
3
4
5
6
7
8
/***
/* 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;
}

这真的适用于任意宽度的树。

如果需要二叉树,通常更容易与命名字段一起使用:

1
2
3
4
5
private class Node { // Using package visibility is an option
  String value;
  Node left;
  Node right;
}

或者如果你想要一个特里尔:

1
2
3
4
private class Node {
  String value;
  Map<char, Node> nodes;
}

现在你说你想要

to be able to get all the children (some sort of list or array of Strings) given an input string representing a given node

听起来像你的家庭作业。不过,既然我有理由确定现在已经过了最后期限…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
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()));
 }
}

这样你就可以像:

1
2
3
4
5
6
7
8
$ 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
[]

1
2
3
4
5
6
7
8
9
10
public abstract class Node {
  List<Node> children;

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

简单易用。要使用它,请扩展它:

1
2
3
4
5
public class MenuItem extends Node {
  String label;
  String href;
  ...
}

由于问题要求提供可用的数据结构,因此可以从列表或数组构造树:

1
2
3
4
5
6
7
8
Object[] tree = new Object[2];
tree[0] ="Hello";
{
  Object[] subtree = new Object[2];
  subtree[0] ="Goodbye";
  subtree[1] ="";
  tree[1] = subtree;
}

instanceof可用于确定元素是子树还是终端节点。


例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
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;
    }
}

我写了一个基于"hashmap"的小"treemap"类,它支持添加路径:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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"(通用)类型的树,但不支持在其节点中存储额外的数据。如果您有这样的文件:

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

然后,您可以通过执行以下操作使其成为树:

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

你会得到一棵漂亮的树。它应该很容易适应你的需要。


在过去,我只是使用了一个嵌套的映射。这是我今天用的,很简单,但它符合我的需要。也许这对另一个有用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
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"));
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
    // 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);
  }
}


Java中没有特定的数据结构,适合您的需求。您的需求非常具体,因此需要设计自己的数据结构。查看您的需求,任何人都可以说您需要某种具有特定功能的n元树。您可以按以下方式设计数据结构:

  • 树节点的结构类似于节点中的内容,子节点列表类似于:类节点字符串值;列出子级;
  • 您需要检索给定字符串的子级,因此您可以有两种方法:1:节点searchnode(string str),将返回与给定输入值相同的节点(使用bfs进行搜索)2:列表get children(string str):此方法将在内部调用searchnode以获取具有相同字符串的节点,然后创建al的列表l字符串值的子级和返回。
  • 您还需要在树中插入一个字符串。您必须编写一个方法,比如void insert(字符串父级,字符串值):这将再次搜索值等于父级的节点,然后您可以创建具有给定值的节点,并将其添加到找到的父级的子级列表中。
  • 我建议您在类node string value;list children;中编写节点的结构,在另一个nodeUtils类中编写所有其他方法,如search、insert和getchildren,这样您也可以通过树根在特定的树上执行操作,例如:class nodeUtils公共静态节点搜索(node root,string value)//执行bfs并返回node


    您可以使用ApacheJMeter中包含的hashtree类,它是雅加达项目的一部分。

    hashtree类包含在包org.apache.jorphan.collections中。虽然这个包不是在JMeter项目之外发布的,但是您可以很容易地获得它:

    1)下载JMeter源。

    2)创建新包。

    3)复制到it/src/jorphan/org/apache/jorphan/collections/。除data.java外的所有文件

    4)也复制/src/jorphan/org/apache/jorphan/util/jorphanutils.java

    5)hashtree可以使用。


    我编写了一个树库,它可以很好地使用Java8,并且没有其他依赖项。它还提供了对函数式编程的一些想法的松散解释,并允许您映射/过滤/修剪/搜索整个树或子树。

    网址:https://github.com/rutledgepaulv/prune

    这个实现在索引方面没有做任何特殊的工作,我也没有偏离递归,所以使用大型树时性能可能会降低,您可能会破坏堆栈。但是如果你只需要一棵小到中等深度的直截了当的树,我认为它足够好用了。它提供了一个健全(基于值)的平等定义,它还具有一个ToString实现,让您可以可视化树!


    请检查下面的代码,其中我使用了树数据结构,而不使用集合类。代码可能有缺陷/改进,但请使用此代码仅供参考。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    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();

        }

    }


    可以在Java.UTL.*中使用TeeSeTepe类。它像二进制搜索树一样工作,所以已经排序了。Treeset类实现ITerable、Collection和Set接口。您可以像集合一样使用迭代器遍历树。

    1
    2
    3
    4
    5
    TreeSet<String> treeSet = new TreeSet<String>();
    Iterator<String> it  = treeSet.Iterator();
    while(it.hasNext()){
    ...
    }

    您可以检查,Java doc和其他一些。


    不使用集合框架的树的自定义树实现。它包含树实现中需要的不同的基本操作。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    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);            
        }

    }