Problem while implementing Find() method for a disjoint set - java

Been trying to solve this for a while now. I've been given a Node in a Disjoint Set.The Node's implementation is as a class where either it has a different parent node or is it's own
class Node {
Node parent;
int rank;
//...constructor and method declarations}
Now, I have to implement the Find method for this class with path compression, called the getParent() method. I wrote the following code:
Node getParent(){
while(parent != this)
{
parent = parent.getParent();
}
return parent;
I get infinite recursion with this code. I know it's problematic, but I do not know how to fix it. I tried using the this keyword, but it led to the same errors.
Please help. Also, an insight on how to write this code in an iterative manner would be a great plus.
Also, I would like to restructure the tree such that all intermediate nodes between the node on which the getParent() is called and the root have a common parent i.e. the root node.

The first part of your question is already answered by Stephen, and I think this is complete enough.
About the second part of your question, I assume you have all the nodes in a list. So you have List<Node> allNodes. The needed method to restructure the tree would be:
public void reStructureTree(List<Node> allNodes){
for(Node item: allNodes){
Node p = item.parent;
List<Node> branch = new ArrayList<>();
while (p.parent != p){
branch.add(p);
p = p.parent;
}
for(Node branchItem : branch){
branchItem.parent = p;
}
}
}
The order of this method in the worst case would be O(n^2) and I did not look for a better way, cause you didn't mention the importance of it.

Node getParent() {
while (parent != this) {
parent = parent.getParent();
}
return parent;
}
The problems:
You are mutating the parent field.
You should be testing if the parent's parent is itself ... not this.
Your code should probably be:
Node getParent() {
Node p = parent;
while(p.parent != p) {
p = p.parent;
}
return p;
}
Or recursively:
Node getParent() {
return (parent == this) ? this : parent.getParent();
}
(In this case, the iterative version is safer. You should not get "infinite" recursion, but there is still a risk that you may recurse too deep, with a pathologically deep data structure.)
UPDATE - apparently, it is your intention that getParent should (incrementally) collapse the parent chain of each Node it visit. In that case, the recursive solution would be:
Node getParentAndCollapse() {
if (parent == this) {
return this;
} else {
parent = parent.getParentAndCollapse();
return parent;
}
}
An iterative solution that collapses the entire chain requires two traversals of the chain:
Traverse the chain find the ultimate parent.
Traverse the chain again, updating all the parent fields to refer to the ultimate parent.
Return the ultimate parent.
Something like this
Node getParentAndCollapse() {
Node p = getParent(); // iterative version
Node n = this;
while (n.parent != p) {
Node np = n.parent;
n.parent = p;
n = np;
}
return p;
}

Related

I need to find the total number of nodes of a tree in java

I will receive something like:
public int count (Tree myTree){
}
I already have the Tree definition, getLeft(), getRight() methods.
I have seen some examples, but always they receive a node as parameter, I need to receive the Tree as parameter.
Could anyone please help me? I'm new on this topic.
Thanks
Here Tree is the node class itself, meaning the name is given differently.
So myTree parameter is a node itself of the given Binary Tree, here pointing to the root in the given function.
Now Tree and the node class itself in the picture below, where the right child and left child and the data of the current node are stored.
So to find out the number of nodes of a given tree,
You have to first check if the given myTree is null or not, meaning if the given myTree doesn't have any Root node only.
Then you have to return 0.
int count(Tree myTree)
{
if (myTree == null)
return 0;
int res = 0;
if (myTree.left != null && myTree.right != null)
res++;
res += (count(myTree.left) + count(myTree.right));
return res;
}
Hope it helps :D
A tree in fact is defined by its root node, but let's just say you implemented the Tree in your own way :p and that you have a function to get the root getRoot(), you can use recursion as it follows to count the number of nodes in your tree (we assume that for a node you can access the children with getLeft() and getRight(), you have to implement a function to construct a tree from a node constructTree(Node root)):
public int count (Tree myTree){
Node root = myTree.getRoot();
return root != null ?
1 + count(constructTree(root.getLeft()) +
count(contructTree(root.getRight()))
: 0;
}
Here in count (Tree myTree){ }
Tree is the Node class only and you'll receive root node as a parameter which here is myTree
Because without root node it is impossible to access tree.
And in java Collections there is no such thing as Tree. So rest assured you are on right track.
Assuming Tree == Node as you have described your problem, then one approach is to use recursion:
public static int count(Tree tree) {
Tree left = tree.getLeft();
Tree right = tree.getRight();
return 1 +
(left != null ? count(left) : 0) +
(right != null ? count(right) : 0);
}

How to split a TreeList's children

I have been trying how to write a TreeList but failed so I googled one up and learn't from there. That works but what I am now trying to do and what I cannot find is how to split a TreeList. I have created 2 examples and both have failed me. The program just crashes. I am using Java and the TreeList class I am basing of is http://yet-another-tree-structure.googlecode.com/svn/trunk/java/src/com/tree/.
Original one
public TreeNode<T> removeAndCreate() {
TreeNode<T> tn = new TreeNode<T>(data);
tn.children = children;
tn.elementsIndex = elementsIndex;
elementsIndex.remove(this);
children.remove(this);
return tn;
}
The newer one I am using
public TreeNode<T> split() {
TreeNode<T> tP = parent;
while (tP.isRoot() == false) {
tP = tP.parent;
}
TreeNode<T> tn = new TreeNode<T>(data);
tn.children = children;
tn.elementsIndex = elementsIndex;
tP.elementsIndex.remove(this);
tP.children.remove(this);
return tn;
}
I thank you for the help I receive in advance.
After reviewing the classes you based things on and your second split I am going to assume that split means to take the node in question out of the current tree and return a new tree with node in question as its root. If that is what you are after then a few things need fixing. First of all your split function does:
TreeNode<T> tP = parent;
while (tP.isRoot() == false) {
tP = tP.parent;
}
Problem is that if your current node (this) doesn't have a parent you will get a Null exception thrown (so try splitting the root node and you should get an error). I think you meant:
TreeNode<T> tP = this;
This change will avoid the loop accessing a parent that may be null. Next, you need to delete all the elementsIndex at each level from the parent and above. You then have to remove the children from your direct parent (if you have a parent).
I think the code you might be looking for is below (assuming I haven't missed something):
public TreeNode<T> split() {
// Create a new root node for the tree we split off
TreeNode<T> tn = new TreeNode<T>(data);
tn.children = children;
tn.elementsIndex = elementsIndex;
// For each level of the tree above us make sure we remove
// ourselves from the elementsIndex at EACH LEVEL until we
// finish at the root.
TreeNode<T> tP = this;
while (tP.isRoot() == false) {
tP = tP.parent;
tP.elementsIndex.remove(this);
}
// If this node has a parent remove this node as one of
// our parent's children. We aren't the child of any of the
// levels above our parent
if (parent != null)
this.parent.children.remove(this);
// Return the root of the newly split tree
return tn;
}

Deleteing a Node in a Binary tree

Iunderstand the basis of a deletion algorithm in a Binary Search tree and have created the following code to delete the largest value from the tree.
public void DelLargest()
{
Node<T> del = this;
boolean child = this.left.empty();
boolean child2 = this.right.empty();
right.DelLargest();
if(child && child2)
this.head = null;
else if(child == true && child2 == false)
this.head = left;
}
Basically what I have is that the recursion runs until 'this' is the rightmost node and then checks two cases, whether 'this' is a leaf, or whether 'this' has a left child. (The other case normally associated with this kind of algorithm is redundant because in finding the node with the largest value, I have gone as right as I can go.) The trouble I am having is getting the current node to then either point to null or to the value at Node left.
Note : This is what my instructor referred to as a "modern" Binary search Tree wherein a vertex or "filled" node and a nil or "empty" node are two subclasses of Interface Node which define the characteristics of each type.
I've managed to narrow the problem down to the fact that I do not have a method that returns a value of a given Node. Working on that now, input would be appreciated.
As suggested in the other answer you should use iterative approach.
In a BST the largest value is the rightmost node.
So do a scan and keep going right until you hit a null.
In the scan keep track of three nodes. (gpnode, pnode, node).
Once the scan is done you will have (gpnode,pnode,null)
Now there are 2 cases.
case 1:
pnode is a leaf. So change the edge (gpnode,pnode) to (gpnode,null)
case 2: (EDITED)
pnode.lChild is not null. Note that pnode.rChild will be null as the search would have terminated at that point.
Now change the edge (gpnode,pnode) to (gpnode,pnode.lChild)
Here is the pseudo code:
public class Node
{
long key;
Node lChild;
Node rChild;
}
public void DelLargest()
{
Node gpnode = null;
Node pnode = null;
Node node = root;
while(node != null) // keep going right until a null is reached
{
gpnode = pnode;
pnode = node;
node = node.rChild;
}
if(pnode.lChild == null) // its a leaf node So change the edge (gpnode,pnode) to (gpnode,null)
{
if(gpnode.lChild == pnode)
{
gpnode.lChild = null;
}
else
{
gpnode.rChild = null;
}
}
else // copy lChild's key to this node and delete lChild
{
if(gpnode.lChild == pnode)
{
gpnode.lChild = pnode.lChild;
}
else
{
gpnode.rChild = pnode.lChild;
}
}
}
You've got the right idea. What you want to do is keep a reference to the right most nodes parent, and the right most nodes left child so then when you delete it you can attach the two.
Here's an iterative solution. This will generally be more efficient than recursion, but if you want recursion you should be able to adapt it:
public void delLargest() {
// get rightmost node's parent
Node<T> current = root;
while(current.right != null && current.right.right != null) {
current = current.right;
}
// get the rightmost nodes left node
Node<T> left = current.right.left;
// attach the parent and left
current.right = left;
// nothing points to the right most node anymore, so it will be garbage collected
}

java alogrithm: find pre/next leaf node that meet special condition from any node in a tree

I need to write a function to find previous/next leaf node that meet special condition from any node in a singly rooted tree. (in the parent first order)
The API would be something like this:
Node findNextLeafNode(Node currentNode, Condition condition);
Node findPretLeafNode(Node currentNode, Condition condition);
where currentNode is any node in a tree, and Node is defined as:
interface Node{
/** #return the Node's parent or null if Node is root */
Node getParent();
/** #return true if node is root */
boolean isRoot();
/** #return non-null array of child nodes (zero length for leaf nodes) */
Node[] getChildren();
/** #return the number of child nodes. If node is leaf, value is 0 */
int getChildCount();
}
And the Condition interface defines the semantics of checking a constraint against a given Node.
interface Condition{
/** #return true if provided node meets the condition */
boolean check(Node node);
}
My question:
Is there an existing library or algorithm for such a common scenario? I am open to either stack based or recursive algorithms. Pseudocode, links to open source libraries, or if you care to share you own code, would be appreciated.
(If not, I need to spend time to invent the same wheel again and paste it here later for sharing.)
Thanks.
-----------------------------write a method to getNext()........
// currentNode must be descendant of root
public static Node getNextNode(Node currentNode, Node root)
{
// 1. if is has child, next is its first child
if (currentNode.getChildSize() > 0) {
return currentNode.getChildren()[0];
}
// 2. if it has no child, check if its is the last child of his parent
else {
// if it is root and has no children, return null
if (currentNode == root) {
return null;
}
// else should have parent which is or under root;
Node parent = currentNode.getParent();
int index = getIndex(currentNode);
if (!isLastofParent(currentNode)) {
// ----a. if not last, next is his parent's next
return currentNode.getParent().getChildren()[index + 1];
}
else {
// ----b. if it is the last one, return its parent's next right if there is. while until root
Node tmp = parent;
while (tmp != root) {
int parentIndex = getIndex(tmp);
if (!isLastofParent(tmp)) {
return tmp.getParent().getChildren()[parentIndex + 1];
}
tmp = tmp.getParent();
}
}
}
return null;
}
private static boolean isLastofParent(Node node)
{
if (getIndex(node) == node.getParent().getChildSize() - 1) {
return true;
}
return false;
}
private static int getIndex(Node currentNode)
{
Node parent = currentNode.getParent();
for (int i = 0; i < parent.getChildSize(); i++) {
if (parent.getChildren()[i] == currentNode) {
return i;
}
}
//TODO: error condition handling, will not happen if tree not change
return -1;
}
------------------------a full search is much easier............
public static Node getNextFailNode(Node currentNode, Node root, Condition condition)
{
boolean foundCurrentNode = false;
Stack<Node> stack = new Stack<Node>();
stack.push(root);
while (!stack.isEmpty()) {
Node tmp = stack.pop();
System.out.println("-popup---------" +tmp+ " ");
if (foundCurrentNode && checkCondition(tmp, condition)) {
return tmp;
}
if (tmp == currentNode) {
foundCurrentNode = true;
}
if (tmp.getChildSize() > 0) {
for (int i = tmp.getChildSize() - 1; i >= 0; i--) {
stack.push(tmp.getChildren()[i]);
}
}
}
return null;
}
This maybe way overblown for what you need, but it can support what you want:
There is a graph traversal language: Gremlin. Typically bolted on top of something like Neo4j, but any graph data structure (e.g. a singly rooted directed tree) can be wrapped to support the API. Take a look at Blueprints projects to find out how it is done.
[edit: for something less heavy]
Perhaps JGraphT is what you want. Also take a look at this question on SO. It is not an exact duplicate, but you should find it helpful.
Write an iterator for your tree that can be initialized from any node and uses pre/in/post-order traversal (Of course it should be bi-directional).
This is basically writing one simple algorithm that at least to me seem basic.
Once you have an iterator all you need is to iterate your way to the next node which is a leaf and the condition holds for it.
If you have trouble with any specific part just ask and I'll improve my answer.
Based on the fact that you already have defined your interfaces, and you say the graph-traversal libraries are too heavyweight, you probably should just write it yourself. It would be an absolutely trivial amount of code. (This page contains some code if you need help.)
(One suggestion for your API: don't put a boolean isRoot(); method on Node, that's a waste of bits unless you have a very good reason to do so. The code that builds the tree should just refer to the root node.)

Easy way to find Subtree in a Tree

I'm writing some code that uses a Tree (a regular tree that can have an unlimited number of nodes, but no crossover, i.e. two parent nodes will not point the the same child node). Anyway, two things:
1) Are there any well-known algorithms for finding a sub-tree within a tree.
2) Are there any Java libraries (or any libraries for that matter) that already implement this algorithm? Even if there are none, can anyone recommend any good general purpose Java tree library?
I want to use these trees for holding data in a tree format, not for their searching capabilities.
To expand a bit: I'm using the tree as part of game to keep a history of what happens when a certain events happen. For example, an A can hit a B which can hit two A's which can hit another two A's etc.
That would look something like:
A
|
B
/
A
/ \
A A
/ \
A A
Of course there's more than just A and B. What I want to do is (for an achievement system) is be able to tell when, say an A has hit two A's:
A
/ \
A A
I want to be able to easily know if the first tree contains that subtree. And I don't want to have to write all the code for doing so if I don't have to :)
Looks like a straightforward algorithm: Find the root of the search tree in the game tree and check whether the children of the search tree are a subset of the children in the game tree.
From your explanations, I'm not sure whether the search tree
A
/ \
A A
should match this tree:
A
/|\
A C A
(i.e. if non-matching children are supposed to be ignored.)
Anyway, here's the code I just toyed around with. It's a fully running example and comes with a main method and a simple Node class. Feel free to play with it:
import java.util.Vector;
public class PartialTreeMatch {
public static void main(String[] args) {
Node testTree = createTestTree();
Node searchTree = createSearchTree();
System.out.println(testTree);
System.out.println(searchTree);
partialMatch(testTree, searchTree);
}
private static boolean partialMatch(Node tree, Node searchTree) {
Node subTree = findSubTreeInTree(tree, searchTree);
if (subTree != null) {
System.out.println("Found: " + subTree);
return true;
}
return false;
}
private static Node findSubTreeInTree(Node tree, Node node) {
if (tree.value == node.value) {
if (matchChildren(tree, node)) {
return tree;
}
}
Node result = null;
for (Node child : tree.children) {
result = findSubTreeInTree(child, node);
if (result != null) {
if (matchChildren(tree, result)) {
return result;
}
}
}
return result;
}
private static boolean matchChildren(Node tree, Node searchTree) {
if (tree.value != searchTree.value) {
return false;
}
if (tree.children.size() < searchTree.children.size()) {
return false;
}
boolean result = true;
int treeChildrenIndex = 0;
for (int searchChildrenIndex = 0;
searchChildrenIndex < searchTree.children.size();
searchChildrenIndex++) {
// Skip non-matching children in the tree.
while (treeChildrenIndex < tree.children.size()
&& !(result = matchChildren(tree.children.get(treeChildrenIndex),
searchTree.children.get(searchChildrenIndex)))) {
treeChildrenIndex++;
}
if (!result) {
return result;
}
}
return result;
}
private static Node createTestTree() {
Node subTree1 = new Node('A');
subTree1.children.add(new Node('A'));
subTree1.children.add(new Node('A'));
Node subTree2 = new Node('A');
subTree2.children.add(new Node('A'));
subTree2.children.add(new Node('C'));
subTree2.children.add(subTree1);
Node subTree3 = new Node('B');
subTree3.children.add(subTree2);
Node root = new Node('A');
root.children.add(subTree3);
return root;
}
private static Node createSearchTree() {
Node root = new Node('A');
root.children.add(new Node('A'));
root.children.add(new Node('A'));
return root;
}
}
class Node {
char value;
Vector<Node> children;
public Node(char val) {
value = val;
children = new Vector<Node>();
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append('(');
sb.append(value);
for (Node child : children) {
sb.append(' ');
sb.append(child.toString());
}
sb.append(')');
return sb.toString();
}
}
Are you looking for any particular constraints on a subtree? If not, a simple traversal should suffice for identifying subtrees (basically treat each node as the root of a subtree).
I believe you'll find that the API you'll want for a tree varies a great deal by your particular application -- so much that generic implementations are not very useful. Perhaps if you could tell us what kind of application the tree will be used for, we could provide particulars.
Also, if you're just using a tree for data storage, you might want to ask yourself why you need a tree. That answer should also answer the question in my previous paragraph.
I wonder if there's an extension of the Knuth algorithm that would be more efficient than a naive traversal...
If there is one big, static, tree and you will be searching for many subtrees in the same big tree, you might want to annotate each node with the set of hashes of all of its subtrees to a given depth depending on how much storage you're willing to expend on that functionality. Then build a map from hash values to the set of nodes that are roots of a subtree with that hash value. Then just check each one of those, presumably much cheaper than a traversal, for the hash of the root of the query tree to that same depth.

Categories