I've been looking for a good non-binary tree implementation that matches my needs but haven't found one.
I need a non-binary tree, in which the number of children is arbitrary, and that can be traversed. This tree is built by user input so I need to have a cyclic check. Other functionality includes removing nodes (and their children), traversal to get the children of a node (and the children of children) and adding children (and other trees).
Examples of implementations I found online include using the firstchild-nextsibling method and parent-child links to a node. The problem with the firstchild-nextsibling method is adding trees and nodes to a tree. The parent-child method seems reasonable but I haven't found any implementation that adds whole trees as children and has cyclic checks.
An example of such implementation:
A
/ \
U W
The user then chooses to create another tree:
B
/ \
X R
and then adds B as a child of W. The full tree would be:
A
/ \
U W
\
B
/ \
X R
If there's a better way to implement this data structure then I would be glad to hear it, because I can't think of anything else. Any help would be very appreciated. Thank you!
EDIT: Some code I wrote.
public class TreeNode<T> {
private T data;
private TreeNode<T> firstChild;
private TreeNode<T> nextSibling;
private TreeNode<T> parent;
public TreeNode(T data) {
this.data = data;
}
public boolean isRoot() {
return this.parent == null;
}
public boolean isaLeaf() {
return this.firstChild == null;
}
public TreeNode<T> getFirstChild(){
return firstChild;
}
public void addChild(TreeNode<T> child) {
child.parent = this;
if (this.firstChild == null) {
this.firstChild = child;
} else {
child.nextSibling = firstChild;
firstChild = child;
}
}
public TreeNode<T> getParent(){
return parent;
}
public TreeNode<T> getNextSibling() {
return nextSibling;
}
public T getData() {
return data;
}
}
EDIT 2: My tree allows for the addition of similar nodes, but what it doesn't allow for is creating an infinite cycle. An example of such a cycle would be adding W as a child of R. I was thinking of having each level as a linked list for easier sorting, but I'm not sure if that makes any sense. Any thoughts?
You can add cyclic check to the addChild method:
public void addChild(TreeNode<T> child) {
if (!child.isRoot()) {
throw new IllagalArgumentException();
}
TreeNode myRoot = this;
while (!myRoot.isRoot()) {
myRoot = myRoot.parent();
}
if (child == myRoot) {
throw new IllagalArgumentException();
}
// now we can safely set parent
child.parent = this;
I assume that your intention is for the data structure to be a tree, and not a DAG (directed acyclic graph). Here are some properties that distinguish trees from graphs.
In a tree:
In a graph or DAG, some nodes may have more than one parent and there may be multiple root nodes, or no root nodes.
Clearly in pure data structure terms, the same representational types can represent a tree, a graph, or a DAG, depending on how you put them together. Therefore, to ensure that your data structure is a tree, you need to maintain the properties above. This can be done by restricting the transformation you can perform, and placing some preconditions on them. The following should be enough:
Add node n1 as a child of node n2:
Remove node n1 from parent node n2:
As you can see, the only slightly tricky thing that you need to do is to check that n1 and n2 don't (already) have the same root before adding one to the other; this can be done using a simple recursive helper function:
TreeNode root(TreeNode n) {
return (n.parent == null) ? n : root(n.parent);
}
then
void add(TreeNode n1, Tree node n2) {
if (root(n1) != n1 || n1 == root(n2)) {
throw new BadTreeTransformation(...);
}
If you restrict the user interface so that all tree transformations are composed of insert and remove operations as above, then the tee invariants will be maintained.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.